xref: /AOO41X/main/accessibility/bridge/org/openoffice/java/accessibility/Window.java (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 package org.openoffice.java.accessibility;
29 
30 import com.sun.star.uno.*;
31 import com.sun.star.accessibility.*;
32 
33 public class Window extends java.awt.Window implements javax.accessibility.Accessible, NativeFrame {
34     protected XAccessibleComponent unoAccessibleComponent;
35 
36     boolean opened = false;
37     boolean visible = false;
38 
39     java.awt.EventQueue eventQueue = null;
40 
41     public Window(java.awt.Window owner, XAccessibleComponent xAccessibleComponent) {
42         super(owner);
43         initialize(xAccessibleComponent);
44     }
45 
46     private void initialize(XAccessibleComponent xAccessibleComponent) {
47         unoAccessibleComponent = xAccessibleComponent;
48         eventQueue = java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue();
49         XAccessibleEventBroadcaster broadcaster = (XAccessibleEventBroadcaster)
50             UnoRuntime.queryInterface(XAccessibleEventBroadcaster.class,
51             unoAccessibleComponent);
52         if (broadcaster != null) {
53             broadcaster.addEventListener(new AccessibleWindowListener());
54         }
55     }
56 
57     java.awt.Component initialComponent = null;
58 
59     public java.awt.Component getInitialComponent() {
60         if (Build.DEBUG) {
61             System.err.println("returning initial component object of class: " + initialComponent.getClass().getName());
62         }
63         return initialComponent;
64     }
65 
66     public void setInitialComponent(java.awt.Component c) {
67         initialComponent = c;
68     }
69 
70     public Integer getHWND() {
71         return null;
72     }
73 
74     /**
75     * Determines whether this <code>Component</code> is showing on screen.
76     * This means that the component must be visible, and it must be in a
77     * <code>container</code> that is visible and showing.
78     * @see       #addNotify
79     * @see       #removeNotify
80     * @since JDK1.0
81     */
82     public boolean isShowing() {
83         if (isVisible()) {
84             java.awt.Container parent = getParent();
85             return (parent == null) || parent.isShowing();
86         }
87         return false;
88     }
89 
90     /**
91     * Makes this <code>Component</code> displayable by connecting it to a
92     * native screen resource.
93     * This method is called internally by the toolkit and should
94     * not be called directly by programs.
95     * @see       #isDisplayable
96     * @see       #removeNotify
97     * @since JDK1.0
98     */
99     public void addNotify() {
100 //      createHierarchyEvents(0, null, null, 0, false);
101     }
102 
103     /**
104     * Makes this <code>Component</code> undisplayable by destroying it native
105     * screen resource.
106     * This method is called by the toolkit internally and should
107     * not be called directly by programs.
108     * @see       #isDisplayable
109     * @see       #addNotify
110     * @since JDK1.0
111     */
112     public void removeNotify() {
113     }
114 
115         /**
116          * Determines if the object is visible.  Note: this means that the
117          * object intends to be visible; however, it may not in fact be
118          * showing on the screen because one of the objects that this object
119          * is contained by is not visible.  To determine if an object is
120          * showing on the screen, use <code>isShowing</code>.
121          *
122          * @return true if object is visible; otherwise, false
123          */
124     public boolean isVisible(){
125         return visible;
126     }
127 
128     /**
129     * Shows or hides this component depending on the value of parameter
130     * <code>b</code>.
131     * @param b  if <code>true</code>, shows this component;
132     * otherwise, hides this component
133     * @see #isVisible
134     * @since JDK1.1
135     */
136     public void setVisible(boolean b) {
137         if (visible != b){
138             visible = b;
139             if (b) {
140                 // If it is the first show, fire WINDOW_OPENED event
141                 if (!opened) {
142                     postWindowEvent(java.awt.event.WindowEvent.WINDOW_OPENED);
143                     opened = true;
144                 }
145                 postComponentEvent(java.awt.event.ComponentEvent.COMPONENT_SHOWN);
146             } else {
147                 postComponentEvent(java.awt.event.ComponentEvent.COMPONENT_HIDDEN);
148             }
149         }
150     }
151 
152     public void dispose() {
153         setVisible(false);
154         postWindowEvent(java.awt.event.WindowEvent.WINDOW_CLOSED);
155 
156         // Transfer window focus back to the owner window if it is still the active frame
157         if ((getOwner() instanceof Frame && ((Frame) getOwner()).active) ||
158                 (getOwner() instanceof Dialog && ((Dialog) getOwner()).active)) {
159             eventQueue.postEvent(new java.awt.event.WindowEvent(getOwner(),
160                 java.awt.event.WindowEvent.WINDOW_GAINED_FOCUS));
161         }
162     }
163 
164     protected void postWindowEvent(int i) {
165         eventQueue.postEvent(new java.awt.event.WindowEvent(this, i));
166     }
167 
168     protected void postComponentEvent(int i) {
169         eventQueue.postEvent(new java.awt.event.ComponentEvent(this, i));
170     }
171 
172     /**
173     * Update the proxy objects appropriatly on property change events
174     */
175     protected class AccessibleWindowListener implements XAccessibleEventListener {
176 
177         protected AccessibleWindowListener() {
178         }
179 
180         // The only expected state changes are ACTIVE and VISIBLE
181         protected void setComponentState(short state, boolean enable) {
182             switch (state) {
183                 case AccessibleStateType.ICONIFIED:
184                     postWindowEvent(enable ?
185                         java.awt.event.WindowEvent.WINDOW_ICONIFIED :
186                         java.awt.event.WindowEvent.WINDOW_DEICONIFIED);
187                     break;
188                 case AccessibleStateType.SHOWING:
189                 case AccessibleStateType.VISIBLE:
190                     setVisible(enable);
191                     break;
192                 default:
193                     if (Build.DEBUG) {
194 //                      System.err.println("[frame]: " + getTitle() + "unexpected state change " + state);
195                     }
196                     break;
197             }
198         }
199 
200         /** Updates the accessible name and fires the appropriate PropertyChangedEvent */
201         protected void handleNameChangedEvent(Object any) {
202             try {
203                 // This causes the property change event to be fired in the VCL thread
204                 // context. If this causes problems, it has to be deligated to the java
205                 // dispatch thread ..
206                 javax.accessibility.AccessibleContext ac = accessibleContext;
207                 if (ac!= null) {
208                     ac.setAccessibleName(AnyConverter.toString(any));
209                 }
210             } catch (com.sun.star.lang.IllegalArgumentException e) {
211             }
212         }
213 
214         /** Updates the accessible description and fires the appropriate PropertyChangedEvent */
215         protected void handleDescriptionChangedEvent(Object any) {
216             try {
217                 // This causes the property change event to be fired in the VCL thread
218                 // context. If this causes problems, it has to be deligated to the java
219                 // dispatch thread ..
220                 if (accessibleContext != null) {
221                     accessibleContext.setAccessibleDescription(AnyConverter.toString(any));
222                 }
223             } catch (com.sun.star.lang.IllegalArgumentException e) {
224             }
225         }
226 
227         /** Updates the internal states and fires the appropriate PropertyChangedEvent */
228         protected void handleStateChangedEvent(Object any1, Object any2) {
229             try {
230                 if (AnyConverter.isShort(any1)) {
231                     setComponentState(AnyConverter.toShort(any1), false);
232                 }
233 
234                 if (AnyConverter.isShort(any2)) {
235                     setComponentState(AnyConverter.toShort(any2), true);
236                 }
237             } catch (com.sun.star.lang.IllegalArgumentException e) {
238             }
239         }
240 
241         /** Fires a visible data property change event */
242         protected void handleVisibleDataEvent() {
243             javax.accessibility.AccessibleContext ac = accessibleContext;
244             if (ac != null) {
245                 ac.firePropertyChange(javax.accessibility.AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, null, null);
246             }
247         }
248 
249         /** Called by OpenOffice process to notify property changes */
250         public void notifyEvent(AccessibleEventObject event) {
251             switch (event.EventId) {
252                 case AccessibleEventId.NAME_CHANGED:
253                     // Set the accessible name for the corresponding context, which will fire a property
254                     // change event itself
255                     handleNameChangedEvent(event.NewValue);
256                     break;
257                 case AccessibleEventId.DESCRIPTION_CHANGED:
258                     // Set the accessible description for the corresponding context, which will fire a property
259                     // change event itself - so do not set propertyName !
260                     handleDescriptionChangedEvent(event.NewValue);
261                     break;
262                 case AccessibleEventId.STATE_CHANGED:
263                     // Update the internal state set and fire the appropriate PropertyChangedEvent
264                     handleStateChangedEvent(event.OldValue, event.NewValue);
265                     break;
266                 case AccessibleEventId.CHILD:
267                     if (AnyConverter.isObject(event.OldValue)) {
268                         AccessibleObjectFactory.removeChild(Window.this, event.OldValue);
269                     } else if (AnyConverter.isObject(event.NewValue)) {
270                         AccessibleObjectFactory.addChild(Window.this, event.NewValue);
271                     }
272                     break;
273                 case AccessibleEventId.VISIBLE_DATA_CHANGED:
274                 case AccessibleEventId.BOUNDRECT_CHANGED:
275                     handleVisibleDataEvent();
276                     break;
277                 default:
278                     // Warn about unhandled events
279                     if(Build.DEBUG) {
280                         System.out.println(this + ": unhandled accessibility event id=" + event.EventId);
281                     }
282             }
283         }
284 
285         /** Called by OpenOffice process to notify that the UNO component is disposing */
286         public void disposing(com.sun.star.lang.EventObject eventObject) {
287         }
288     }
289 
290     protected javax.accessibility.AccessibleContext accessibleContext = null;
291 
292     /** Returns the AccessibleContext associated with this object */
293     public javax.accessibility.AccessibleContext getAccessibleContext() {
294         if (accessibleContext == null) {
295             accessibleContext = new AccessibleWindow();
296 //          accessibleContext.setAccessibleName(getTitle());
297         }
298         return accessibleContext;
299     }
300 
301     protected class AccessibleWindow extends java.awt.Window.AccessibleAWTWindow {
302         protected AccessibleWindow() {
303             super();
304         }
305 
306         protected java.awt.event.ComponentListener accessibleComponentHandler = null;
307 
308         /**
309         * Fire PropertyChange listener, if one is registered,
310         * when shown/hidden..
311         */
312         protected class AccessibleComponentHandler implements java.awt.event.ComponentListener {
313             public void componentHidden(java.awt.event.ComponentEvent e)  {
314                 AccessibleWindow.this.firePropertyChange(
315                     javax.accessibility.AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
316                     javax.accessibility.AccessibleState.VISIBLE, null);
317             }
318 
319             public void componentShown(java.awt.event.ComponentEvent e)  {
320                 AccessibleWindow.this.firePropertyChange(
321                     javax.accessibility.AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
322                     null, javax.accessibility.AccessibleState.VISIBLE);
323             }
324 
325             public void componentMoved(java.awt.event.ComponentEvent e)  {
326             }
327 
328             public void componentResized(java.awt.event.ComponentEvent e)  {
329             }
330         } // inner class AccessibleComponentHandler
331 
332         protected java.awt.event.ContainerListener accessibleContainerHandler = null;
333 
334         /**
335         * Fire PropertyChange listener, if one is registered,
336         * when children added/removed.
337         */
338 
339         protected class AccessibleContainerHandler implements java.awt.event.ContainerListener {
340             public void componentAdded(java.awt.event.ContainerEvent e) {
341                 java.awt.Component c = e.getChild();
342                 if (c != null && c instanceof javax.accessibility.Accessible) {
343                     AccessibleWindow.this.firePropertyChange(
344                         javax.accessibility.AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
345                         null, ((javax.accessibility.Accessible) c).getAccessibleContext());
346                 }
347             }
348             public void componentRemoved(java.awt.event.ContainerEvent e) {
349                 java.awt.Component c = e.getChild();
350                 if (c != null && c instanceof javax.accessibility.Accessible) {
351                     AccessibleWindow.this.firePropertyChange(
352                         javax.accessibility.AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
353                         ((javax.accessibility.Accessible) c).getAccessibleContext(), null);
354                 }
355             }
356         }
357 
358         protected int propertyChangeListenerCount = 0;
359 
360         /**
361         * Add a PropertyChangeListener to the listener list.
362         *
363         * @param listener  The PropertyChangeListener to be added
364         */
365         public void addPropertyChangeListener(java.beans.PropertyChangeListener listener) {
366             if (propertyChangeListenerCount++ == 0) {
367                 accessibleContainerHandler = new AccessibleContainerHandler();
368                 Window.this.addContainerListener(accessibleContainerHandler);
369 
370                 accessibleComponentHandler = new AccessibleComponentHandler();
371                 Window.this.addComponentListener(accessibleComponentHandler);
372             }
373             super.addPropertyChangeListener(listener);
374         }
375 
376         /**
377         * Remove a PropertyChangeListener from the listener list.
378         * This removes a PropertyChangeListener that was registered
379         * for all properties.
380         *
381         * @param listener  The PropertyChangeListener to be removed
382         */
383         public void removePropertyChangeListener(java.beans.PropertyChangeListener listener) {
384             if (--propertyChangeListenerCount == 0) {
385                 Window.this.removeComponentListener(accessibleComponentHandler);
386                 accessibleComponentHandler = null;
387 
388                 Window.this.removeContainerListener(accessibleContainerHandler);
389                 accessibleContainerHandler = null;
390             }
391             super.removePropertyChangeListener(listener);
392         }
393 
394         /*
395         * AccessibleComponent
396         */
397 
398         /** Returns the background color of the object */
399         public java.awt.Color getBackground() {
400             try {
401                 return new java.awt.Color(unoAccessibleComponent.getBackground());
402             } catch (com.sun.star.uno.RuntimeException e) {
403                 return null;
404             }
405         }
406 
407         public void setBackground(java.awt.Color c) {
408             // Not supported by UNO accessibility API
409         }
410 
411         /** Returns the foreground color of the object */
412         public java.awt.Color getForeground() {
413             try {
414                 return new java.awt.Color(unoAccessibleComponent.getForeground());
415             } catch (com.sun.star.uno.RuntimeException e) {
416                 return null;
417             }
418         }
419 
420         public void setForeground(java.awt.Color c) {
421             // Not supported by UNO accessibility API
422         }
423 
424         public java.awt.Cursor getCursor() {
425             // Not supported by UNO accessibility API
426             return null;
427         }
428 
429         public void setCursor(java.awt.Cursor cursor) {
430             // Not supported by UNO accessibility API
431         }
432 
433         public java.awt.Font getFont() {
434             // FIXME
435             return null;
436         }
437 
438         public void setFont(java.awt.Font f) {
439             // Not supported by UNO accessibility API
440         }
441 
442         public java.awt.FontMetrics getFontMetrics(java.awt.Font f) {
443             // FIXME
444             return null;
445         }
446 
447         public boolean isEnabled() {
448             return Window.this.isEnabled();
449         }
450 
451         public void setEnabled(boolean b) {
452             // Not supported by UNO accessibility API
453         }
454 
455         public boolean isVisible() {
456             return Window.this.isVisible();
457         }
458 
459         public void setVisible(boolean b) {
460             // Not supported by UNO accessibility API
461         }
462 
463         public boolean isShowing() {
464             return Window.this.isShowing();
465         }
466 
467         public boolean contains(java.awt.Point p) {
468             try {
469                 return unoAccessibleComponent.containsPoint(new com.sun.star.awt.Point(p.x, p.y));
470             } catch (com.sun.star.uno.RuntimeException e) {
471                 return false;
472             }
473         }
474 
475         /** Returns the location of the object on the screen. */
476         public java.awt.Point getLocationOnScreen() {
477             try {
478                 com.sun.star.awt.Point unoPoint = unoAccessibleComponent.getLocationOnScreen();
479                 return new java.awt.Point(unoPoint.X, unoPoint.Y);
480             } catch (com.sun.star.uno.RuntimeException e) {
481                 return null;
482             }
483         }
484 
485         /** Gets the location of this component in the form of a point specifying the component's top-left corner */
486         public java.awt.Point getLocation() {
487             try {
488                 com.sun.star.awt.Point unoPoint = unoAccessibleComponent.getLocationOnScreen();
489                 return new java.awt.Point( unoPoint.X, unoPoint.Y );
490             } catch (com.sun.star.uno.RuntimeException e) {
491                 return null;
492             }
493         }
494 
495         /** Moves this component to a new location */
496         public void setLocation(java.awt.Point p) {
497             // Not supported by UNO accessibility API
498         }
499 
500         /** Gets the bounds of this component in the form of a Rectangle object */
501         public java.awt.Rectangle getBounds() {
502             try {
503                 com.sun.star.awt.Rectangle unoRect = unoAccessibleComponent.getBounds();
504                 return new java.awt.Rectangle(unoRect.X, unoRect.Y, unoRect.Width, unoRect.Height);
505             } catch (com.sun.star.uno.RuntimeException e) {
506                 return null;
507             }
508         }
509 
510         /** Moves and resizes this component to conform to the new bounding rectangle r */
511         public void setBounds(java.awt.Rectangle r) {
512             // Not supported by UNO accessibility API
513         }
514 
515         /** Returns the size of this component in the form of a Dimension object */
516         public java.awt.Dimension getSize() {
517             try {
518                 com.sun.star.awt.Size unoSize = unoAccessibleComponent.getSize();
519                 return new java.awt.Dimension(unoSize.Width, unoSize.Height);
520             } catch (com.sun.star.uno.RuntimeException e) {
521                 return null;
522             }
523         }
524 
525         /** Resizes this component so that it has width d.width and height d.height */
526         public void setSize(java.awt.Dimension d) {
527             // Not supported by UNO accessibility API
528         }
529 
530         /** Returns the Accessible child, if one exists, contained at the local coordinate Point */
531         public javax.accessibility.Accessible getAccessibleAt(java.awt.Point p) {
532             try {
533                 java.awt.Component c = AccessibleObjectFactory.getAccessibleComponent(
534                     unoAccessibleComponent.getAccessibleAtPoint(new com.sun.star.awt.Point(p.x, p.y)));
535 
536                 return (javax.accessibility.Accessible) c;
537             } catch (com.sun.star.uno.RuntimeException e) {
538                 return null;
539             }
540         }
541 
542         public boolean isFocusTraversable() {
543             return Window.this.isFocusable();
544         }
545 
546         public void requestFocus() {
547             unoAccessibleComponent.grabFocus();
548         }
549     }
550 }
551 
552