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 package org.openoffice.java.accessibility;
24 
25 import com.sun.star.accessibility.*;
26 import com.sun.star.uno.AnyConverter;
27 import com.sun.star.uno.UnoRuntime;
28 
29 
30 public class Menu extends AbstractButton
31     implements javax.accessibility.Accessible {
32     private java.util.Vector children;
33     protected XAccessibleSelection unoAccessibleSelection = null;
34 
Menu(XAccessible xAccessible, XAccessibleContext xAccessibleContext)35     protected Menu(XAccessible xAccessible,
36         XAccessibleContext xAccessibleContext) {
37         super(xAccessible, xAccessibleContext);
38 
39         try {
40             // Create a vector with the correct initial capacity
41             int count = unoAccessibleContext.getAccessibleChildCount();
42             children = new java.util.Vector(count);
43 
44             // Fill the vector with objects
45             for (int i = 0; i < count; i++) {
46                 java.awt.Component c = getComponent(unoAccessibleContext.getAccessibleChild(i));
47 
48                 if (c != null) {
49                     children.add(c);
50                 }
51             }
52         } catch (com.sun.star.uno.RuntimeException e) {
53             if (Build.DEBUG) {
54                 System.err.println(
55                     "RuntimeException caught during menu initialization: " +
56                     e.getMessage());
57             }
58 
59             if (children == null) {
60                 children = new java.util.Vector(0);
61             }
62         } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
63         }
64     }
65 
add(XAccessible unoAccessible)66     protected synchronized void add(XAccessible unoAccessible) {
67         // The AccessBridge for Windows expects an instance of AccessibleContext
68         // as parameters
69         java.awt.Component c = getComponent(unoAccessible);
70 
71         if (c != null) {
72             try {
73                 children.add(unoAccessible.getAccessibleContext()
74                                           .getAccessibleIndexInParent(), c);
75                 firePropertyChange(javax.accessibility.AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
76                     null,
77                     ((javax.accessibility.Accessible) c).getAccessibleContext());
78             } catch (com.sun.star.uno.RuntimeException e) {
79             }
80         }
81     }
82 
remove(XAccessible unoAccessible)83     protected synchronized void remove(XAccessible unoAccessible) {
84         // The AccessBridge for Windows expects an instance of AccessibleContext
85         // as parameters
86         java.awt.Component c = getComponent(unoAccessible);
87 
88         if (c != null) {
89             try {
90                 children.remove(c);
91                 firePropertyChange(javax.accessibility.AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
92                     ((javax.accessibility.Accessible) c).getAccessibleContext(),
93                     null);
94             } catch (com.sun.star.uno.RuntimeException e) {
95             }
96         }
97     }
98 
add(Object any)99     protected void add(Object any) {
100         try {
101             add((XAccessible) AnyConverter.toObject(
102                     AccessibleObjectFactory.XAccessibleType, any));
103         } catch (com.sun.star.lang.IllegalArgumentException e) {
104         }
105     }
106 
remove(Object any)107     protected void remove(Object any) {
108         try {
109             remove((XAccessible) AnyConverter.toObject(
110                     AccessibleObjectFactory.XAccessibleType, any));
111         } catch (com.sun.star.lang.IllegalArgumentException e) {
112         }
113     }
114 
indexOf(Object child)115     protected synchronized int indexOf(Object child) {
116         return children.indexOf(child);
117     }
118 
getComponent(XAccessible unoAccessible)119     protected java.awt.Component getComponent(XAccessible unoAccessible) {
120         java.awt.Component c = AccessibleObjectFactory.getAccessibleComponent(unoAccessible);
121 
122         if (c == null) {
123             c = AccessibleObjectFactory.createAccessibleComponent(unoAccessible);
124 
125             if (c instanceof javax.accessibility.Accessible) {
126                 ((javax.accessibility.Accessible) c).getAccessibleContext()
127                  .setAccessibleParent(this);
128             }
129         }
130 
131         return c;
132     }
133 
createEventListener()134     protected XAccessibleEventListener createEventListener() {
135         return new AccessibleMenuListener();
136     }
137 
138     /** Creates the AccessibleContext associated with this object */
createAccessibleContext()139     public javax.accessibility.AccessibleContext createAccessibleContext() {
140         return new AccessibleMenu();
141     }
142 
143     /**
144     * Update the proxy objects appropriately on property change events
145     */
146     protected class AccessibleMenuListener
147         extends AccessibleUNOComponentListener {
AccessibleMenuListener()148         protected AccessibleMenuListener() {
149             super();
150         }
151 
152         /** Called by OpenOffice process to notify property changes */
notifyEvent(AccessibleEventObject event)153         public void notifyEvent(AccessibleEventObject event) {
154             switch (event.EventId) {
155                 case AccessibleEventId.CHILD:
156 
157                     if (AnyConverter.isObject(event.OldValue)) {
158                         remove(event.OldValue);
159                     }
160 
161                     if (AnyConverter.isObject(event.NewValue)) {
162                         add(event.NewValue);
163                     }
164 
165                     break;
166 
167                 // #i56539# Java 1.5 does not fire ACCESSIBLE_SELECTION_PROPERTY for menus
168                 case AccessibleEventId.SELECTION_CHANGED:
169                     break;
170 
171                 default:
172                     super.notifyEvent(event);
173             }
174         }
175     }
176 
177     protected class AccessibleMenu extends AccessibleAbstractButton
178         implements javax.accessibility.AccessibleSelection {
AccessibleMenu()179         protected AccessibleMenu() {
180             unoAccessibleSelection = (XAccessibleSelection) UnoRuntime.queryInterface(XAccessibleSelection.class,
181                     unoAccessibleContext);
182         }
183 
184         /** Gets the role of this object */
getAccessibleRole()185         public javax.accessibility.AccessibleRole getAccessibleRole() {
186             return javax.accessibility.AccessibleRole.MENU;
187         }
188 
189         /** Gets the 0-based index of this object in its accessible parent */
getAccessibleIndexInParent()190         public int getAccessibleIndexInParent() {
191             if (getAccessibleParent() instanceof Menu) {
192                 return ((Menu) getAccessibleParent()).indexOf(Menu.this);
193             } else {
194                 return super.getAccessibleIndexInParent();
195             }
196         }
197 
198         /** Returns the number of accessible children of the object */
getAccessibleChildrenCount()199         public synchronized int getAccessibleChildrenCount() {
200             return children.size();
201         }
202 
203         /** Returns the specified Accessible child of the object */
getAccessibleChild( int i)204         public synchronized javax.accessibility.Accessible getAccessibleChild(
205             int i) {
206             try {
207                 if (i < children.size()) {
208                     return (javax.accessibility.Accessible) children.get(i);
209                 } else {
210                     return null;
211                 }
212             } catch (ArrayIndexOutOfBoundsException e) {
213                 return null;
214             }
215         }
216 
217         /** Returns the AccessibleSelection interface for this object */
getAccessibleSelection()218         public javax.accessibility.AccessibleSelection getAccessibleSelection() {
219             // This method is called to determine the SELECTABLE state of every
220             // child, so don't do the query interface here.
221             return this;
222         }
223 
224         /*
225         * AccessibleComponent
226         */
227 
228         /** Returns the Accessible child, if one exists, contained at the local coordinate Point */
getAccessibleAt(java.awt.Point p)229         public javax.accessibility.Accessible getAccessibleAt(java.awt.Point p) {
230             try {
231                 java.awt.Component c = AccessibleObjectFactory.getAccessibleComponent(unoAccessibleComponent.getAccessibleAtPoint(
232                             new com.sun.star.awt.Point(p.x, p.y)));
233 
234                 return (javax.accessibility.Accessible) c;
235             } catch (com.sun.star.uno.RuntimeException e) {
236                 return null;
237             }
238         }
239 
240         /*
241         * AccessibleSelection
242         */
243 
244         /** Returns an Accessible representing the specified selected child of the object */
getAccessibleSelection(int i)245         public javax.accessibility.Accessible getAccessibleSelection(int i) {
246             try {
247                 return (javax.accessibility.Accessible) getComponent(unoAccessibleSelection.getSelectedAccessibleChild(
248                         i));
249             } catch (java.lang.Exception e) {
250                 /*
251                 * Possible exceptions are:
252                 *   java.lang.NullPointerException
253                 *   com.sun.star.uno.RuntimeException
254                 *   com.sun.star.lang.IndexOutOfBoundsException
255                 */
256                 return null;
257             }
258         }
259 
260         /** Adds the specified Accessible child of the object to the object's selection */
addAccessibleSelection(int i)261         public void addAccessibleSelection(int i) {
262             try {
263                 javax.accessibility.Accessible a = getAccessibleChild(i);
264 
265                 // selecting menu items invokes the click action in Java 1.5
266                 if( a instanceof MenuItem )
267                     a.getAccessibleContext().getAccessibleAction().doAccessibleAction(0);
268                 else
269                     unoAccessibleSelection.selectAccessibleChild(i);
270             } catch (java.lang.Exception e) {
271                 /*
272                 * Possible exceptions are:
273                 *   java.lang.NullPointerException
274                 *   com.sun.star.uno.RuntimeException
275                 *   com.sun.star.lang.IndexOutOfBoundsException
276                 */
277             }
278         }
279 
280         /** Clears the selection in the object, so that no children in the object are selected */
clearAccessibleSelection()281         public void clearAccessibleSelection() {
282             try {
283                 unoAccessibleSelection.clearAccessibleSelection();
284             } catch (com.sun.star.uno.RuntimeException e) {
285             }
286         }
287 
288         /** Returns the number of Accessible children currently selected */
getAccessibleSelectionCount()289         public int getAccessibleSelectionCount() {
290             try {
291                 return unoAccessibleSelection.getSelectedAccessibleChildCount();
292             } catch (com.sun.star.uno.RuntimeException e) {
293                 return 0;
294             }
295         }
296 
297         /** Determines if the current child of this object is selected */
isAccessibleChildSelected(int i)298         public boolean isAccessibleChildSelected(int i) {
299             try {
300                 return unoAccessibleSelection.isAccessibleChildSelected(i);
301             } catch (java.lang.Exception e) {
302                 /*
303                 * Possible exceptions are:
304                 *   java.lang.NullPointerException
305                 *   com.sun.star.uno.RuntimeException
306                 *   com.sun.star.lang.IndexOutOfBoundsException
307                 */
308                 return false;
309             }
310         }
311 
312         /** Removes the specified child of the object from the object's selection */
removeAccessibleSelection(int i)313         public void removeAccessibleSelection(int i) {
314             if (isAccessibleChildSelected(i)) {
315                 clearAccessibleSelection();
316             }
317         }
318 
319         /** Causes every child of the object to be selected if the object supports multiple selection */
selectAllAccessibleSelection()320         public void selectAllAccessibleSelection() {
321             // not supported
322         }
323     }
324 }
325