xref: /AOO41X/main/accessibility/bridge/org/openoffice/java/accessibility/Dialog.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 javax.accessibility.AccessibleState;
31 
32 import com.sun.star.uno.*;
33 import com.sun.star.accessibility.*;
34 
35 public class Dialog extends java.awt.Dialog implements javax.accessibility.Accessible, NativeFrame {
36     protected XAccessibleComponent unoAccessibleComponent;
37 
38     boolean opened = false;
39     boolean visible = false;
40     boolean active = false;
41 
42     java.awt.EventQueue eventQueue = null;
43 
44     protected Dialog(java.awt.Frame owner, XAccessibleComponent xAccessibleComponent) {
45         super(owner);
46         initialize(xAccessibleComponent);
47     }
48 
49     protected Dialog(java.awt.Frame owner, String name, XAccessibleComponent xAccessibleComponent) {
50         super(owner, name);
51         initialize(xAccessibleComponent);
52     }
53 
54     protected Dialog(java.awt.Frame owner, String name, boolean modal, XAccessibleComponent xAccessibleComponent) {
55         super(owner, name, modal);
56         initialize(xAccessibleComponent);
57     }
58 
59     private void initialize(XAccessibleComponent xAccessibleComponent) {
60         unoAccessibleComponent = xAccessibleComponent;
61         eventQueue = java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue();
62         XAccessibleEventBroadcaster broadcaster = (XAccessibleEventBroadcaster)
63             UnoRuntime.queryInterface(XAccessibleEventBroadcaster.class,
64             xAccessibleComponent);
65         if (broadcaster != null) {
66             broadcaster.addEventListener(new AccessibleDialogListener());
67         }
68     }
69 
70     java.awt.Component initialComponent = null;
71 
72     public java.awt.Component getInitialComponent() {
73         return initialComponent;
74     }
75 
76     public void setInitialComponent(java.awt.Component c) {
77         initialComponent = c;
78     }
79 
80     public Integer getHWND() {
81         return null;
82     }
83 
84     /**
85     * Determines whether this <code>Component</code> is showing on screen.
86     * This means that the component must be visible, and it must be in a
87     * <code>container</code> that is visible and showing.
88     * @see       #addNotify
89     * @see       #removeNotify
90     * @since JDK1.0
91     */
92     public boolean isShowing() {
93         if (isVisible()) {
94             java.awt.Container parent = getParent();
95             return (parent == null) || parent.isShowing();
96         }
97         return false;
98     }
99 
100     /**
101     * Makes this <code>Component</code> displayable by connecting it to a
102     * native screen resource.
103     * This method is called internally by the toolkit and should
104     * not be called directly by programs.
105     * @see       #isDisplayable
106     * @see       #removeNotify
107     * @since JDK1.0
108     */
109     public void addNotify() {
110 //      createHierarchyEvents(0, null, null, 0, false);
111     }
112 
113     /**
114     * Makes this <code>Component</code> undisplayable by destroying it native
115     * screen resource.
116     * This method is called by the toolkit internally and should
117     * not be called directly by programs.
118     * @see       #isDisplayable
119     * @see       #addNotify
120     * @since JDK1.0
121     */
122     public void removeNotify() {
123     }
124 
125         /**
126          * Determines if the object is visible.  Note: this means that the
127          * object intends to be visible; however, it may not in fact be
128          * showing on the screen because one of the objects that this object
129          * is contained by is not visible.  To determine if an object is
130          * showing on the screen, use <code>isShowing</code>.
131          *
132          * @return true if object is visible; otherwise, false
133          */
134     public boolean isVisible(){
135         return visible;
136     }
137 
138     /**
139     * Shows or hides this component depending on the value of parameter
140     * <code>b</code>.
141     * @param b  if <code>true</code>, shows this component;
142     * otherwise, hides this component
143     * @see #isVisible
144     * @since JDK1.1
145     */
146     public void setVisible(boolean b) {
147         if (visible != b){
148             visible = b;
149             if (b) {
150                 // If it is the first show, fire WINDOW_OPENED event
151                 if (!opened) {
152                     postWindowEvent(java.awt.event.WindowEvent.WINDOW_OPENED);
153                     opened = true;
154                 }
155                 postComponentEvent(java.awt.event.ComponentEvent.COMPONENT_SHOWN);
156             } else {
157                 postComponentEvent(java.awt.event.ComponentEvent.COMPONENT_HIDDEN);
158             }
159         }
160     }
161 
162     public void dispose() {
163         setVisible(false);
164         postWindowEvent(java.awt.event.WindowEvent.WINDOW_CLOSED);
165     }
166 
167     protected void postWindowEvent(int i) {
168         eventQueue.postEvent(new java.awt.event.WindowEvent(this, i));
169     }
170 
171     protected void postComponentEvent(int i) {
172         eventQueue.postEvent(new java.awt.event.ComponentEvent(this, i));
173     }
174 
175     /**
176     * Update the proxy objects appropriatly on property change events
177     */
178     protected class AccessibleDialogListener implements XAccessibleEventListener {
179 
180         protected AccessibleDialogListener() {
181         }
182 
183         protected void setComponentState(short state, boolean enable) {
184             switch (state) {
185                 case AccessibleStateType.ACTIVE:
186                     active = enable;
187                     if (enable) {
188                         AccessibleObjectFactory.postWindowActivated(Dialog.this);
189                     } else {
190                         AccessibleObjectFactory.postWindowLostFocus(Dialog.this);
191                     }
192                     break;
193                 case AccessibleStateType.ICONIFIED:
194                     postWindowEvent(enable ?
195                         java.awt.event.WindowEvent.WINDOW_ICONIFIED :
196                         java.awt.event.WindowEvent.WINDOW_DEICONIFIED);
197                     break;
198                 case AccessibleStateType.VISIBLE:
199                     Dialog.this.setVisible(enable);
200                     break;
201                 default:
202                     if (Build.DEBUG) {
203                         System.err.println("[dialog]: " + getTitle() + "unexpected state change " + state);
204                     }
205                     break;
206             }
207         }
208 
209         /** Updates the accessible name and fires the appropriate PropertyChangedEvent */
210         protected void handleNameChangedEvent(Object any) {
211             try {
212                 String title = AnyConverter.toString(any);
213                 setTitle(title);
214                 // This causes the property change event to be fired in the VCL thread
215                 // context. If this causes problems, it has to be deligated to the java
216                 // dispatch thread ..
217                 javax.accessibility.AccessibleContext ac = accessibleContext;
218                 if (ac!= null) {
219                     ac.setAccessibleName(title);
220                 }
221             } catch (com.sun.star.lang.IllegalArgumentException e) {
222             }
223         }
224 
225         /** Updates the accessible description and fires the appropriate PropertyChangedEvent */
226         protected void handleDescriptionChangedEvent(Object any) {
227             try {
228                 // This causes the property change event to be fired in the VCL thread
229                 // context. If this causes problems, it has to be deligated to the java
230                 // dispatch thread ..
231                 javax.accessibility.AccessibleContext ac = accessibleContext;
232                 if (ac!= null) {
233                     ac.setAccessibleDescription(AnyConverter.toString(any));
234                 }
235             } catch (com.sun.star.lang.IllegalArgumentException e) {
236             }
237         }
238 
239         /** Updates the internal states and fires the appropriate PropertyChangedEvent */
240         protected void handleStateChangedEvent(Object any1, Object any2) {
241             try {
242                 if (AnyConverter.isShort(any1)) {
243                     setComponentState(AnyConverter.toShort(any1), false);
244                 }
245 
246                 if (AnyConverter.isShort(any2)) {
247                     setComponentState(AnyConverter.toShort(any2), true);
248                 }
249             } catch (com.sun.star.lang.IllegalArgumentException e) {
250             }
251         }
252 
253         /** Fires a visible data property change event */
254         protected void handleVisibleDataEvent() {
255             javax.accessibility.AccessibleContext ac = accessibleContext;
256             if (ac != null) {
257                 ac.firePropertyChange(javax.accessibility.AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, null, null);
258             }
259         }
260 
261         /** Called by OpenOffice process to notify property changes */
262         public void notifyEvent(AccessibleEventObject event) {
263             switch (event.EventId) {
264                 case AccessibleEventId.NAME_CHANGED:
265                     // Set the accessible name for the corresponding context, which will fire a property
266                     // change event itself
267                     handleNameChangedEvent(event.NewValue);
268                     break;
269                 case AccessibleEventId.DESCRIPTION_CHANGED:
270                     // Set the accessible description for the corresponding context, which will fire a property
271                     // change event itself - so do not set propertyName !
272                     handleDescriptionChangedEvent(event.NewValue);
273                     break;
274                 case AccessibleEventId.STATE_CHANGED:
275                     // Update the internal state set and fire the appropriate PropertyChangedEvent
276                     handleStateChangedEvent(event.OldValue, event.NewValue);
277                     break;
278                 case AccessibleEventId.CHILD:
279                     if (AnyConverter.isObject(event.OldValue)) {
280                         AccessibleObjectFactory.removeChild(Dialog.this, event.OldValue);
281                     } else if (AnyConverter.isObject(event.NewValue)) {
282                         AccessibleObjectFactory.addChild(Dialog.this, event.NewValue);
283                     }
284                     break;
285                 case AccessibleEventId.VISIBLE_DATA_CHANGED:
286                 case AccessibleEventId.BOUNDRECT_CHANGED:
287                     handleVisibleDataEvent();
288                     break;
289                 default:
290                     // Warn about unhandled events
291                     if(Build.DEBUG) {
292                         System.out.println(this + ": unhandled accessibility event id=" + event.EventId);
293                     }
294             }
295         }
296 
297         /** Called by OpenOffice process to notify that the UNO component is disposing */
298         public void disposing(com.sun.star.lang.EventObject eventObject) {
299         }
300     }
301 
302     javax.accessibility.AccessibleContext accessibleContext = null;
303 
304     /** Returns the AccessibleContext associated with this object */
305     public javax.accessibility.AccessibleContext getAccessibleContext() {
306         if (accessibleContext == null) {
307             accessibleContext = new AccessibleDialog();
308             accessibleContext.setAccessibleName(getTitle());
309         }
310         return accessibleContext;
311     }
312 
313     protected class AccessibleDialog extends java.awt.Dialog.AccessibleAWTDialog {
314         protected AccessibleDialog() {
315             super();
316         }
317 
318         protected java.awt.event.ComponentListener accessibleComponentHandler = null;
319 
320         /**
321         * Fire PropertyChange listener, if one is registered,
322         * when shown/hidden..
323         */
324         protected class AccessibleComponentHandler implements java.awt.event.ComponentListener {
325             public void componentHidden(java.awt.event.ComponentEvent e)  {
326                 AccessibleDialog.this.firePropertyChange(
327                     javax.accessibility.AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
328                     javax.accessibility.AccessibleState.VISIBLE, null);
329             }
330 
331             public void componentShown(java.awt.event.ComponentEvent e)  {
332                 AccessibleDialog.this.firePropertyChange(
333                     javax.accessibility.AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
334                     null, javax.accessibility.AccessibleState.VISIBLE);
335             }
336 
337             public void componentMoved(java.awt.event.ComponentEvent e)  {
338             }
339 
340             public void componentResized(java.awt.event.ComponentEvent e)  {
341             }
342         } // inner class AccessibleComponentHandler
343 
344         protected java.awt.event.WindowListener accessibleWindowHandler = null;
345 
346         /**
347         * Fire PropertyChange listener, if one is registered,
348         * when window events happen
349         */
350         protected class AccessibleWindowHandler implements java.awt.event.WindowListener {
351             /** Invoked when the Window is set to be the active Window. */
352             public void windowActivated(java.awt.event.WindowEvent e) {
353                 AccessibleDialog.this.firePropertyChange(
354                     javax.accessibility.AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
355                     null, javax.accessibility.AccessibleState.ACTIVE);
356                 if (Build.DEBUG) {
357                     System.err.println("[Dialog] " + getTitle() + " is now active");
358                 }
359             }
360 
361             /** Invoked when a window has been closed as the result of calling dispose on the window. */
362             public void windowClosed(java.awt.event.WindowEvent e) {
363                 if (Build.DEBUG) {
364                     System.err.println("[Dialog] " + getTitle() + " has been closed");
365                 }
366             }
367 
368             /** Invoked when the user attempts to close the window from the window's system menu. */
369             public void windowClosing(java.awt.event.WindowEvent e) {
370                 if (Build.DEBUG) {
371                     System.err.println("[Dialog] " + getTitle() + " is closing");
372                 }
373             }
374 
375             /** Invoked when a Window is no longer the active Window. */
376             public void windowDeactivated(java.awt.event.WindowEvent e) {
377                 AccessibleDialog.this.firePropertyChange(
378                     javax.accessibility.AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
379                     javax.accessibility.AccessibleState.ACTIVE, null);
380                 if (Build.DEBUG) {
381                     System.err.println("[Dialog] " + getTitle() + " is no longer active");
382                 }
383             }
384 
385             /** Invoked when a window is changed from a minimized to a normal state. */
386             public void windowDeiconified(java.awt.event.WindowEvent e) {
387                 if (Build.DEBUG) {
388                     System.err.println("[Dialog] " + getTitle() + " has been deiconified");
389                 }
390             }
391 
392             /** Invoked when a window is changed from a normal to a minimized state. */
393             public void windowIconified(java.awt.event.WindowEvent e) {
394                 if (Build.DEBUG) {
395                     System.err.println("[Dialog] " + getTitle() + " has been iconified");
396                 }
397             }
398 
399             /** Invoked the first time a window is made visible. */
400             public void windowOpened(java.awt.event.WindowEvent e) {
401                 if (Build.DEBUG) {
402                     System.err.println("[Dialog] " + getTitle() + " has been opened");
403                 }
404             }
405 
406         } // inner class AccessibleWindowHandler
407 
408         protected java.awt.event.ContainerListener accessibleContainerHandler = null;
409 
410         /**
411         * Fire PropertyChange listener, if one is registered,
412         * when children added/removed.
413         */
414 
415         protected class AccessibleContainerHandler implements java.awt.event.ContainerListener {
416             public void componentAdded(java.awt.event.ContainerEvent e) {
417                 java.awt.Component c = e.getChild();
418                 if (c != null && c instanceof javax.accessibility.Accessible) {
419                     AccessibleDialog.this.firePropertyChange(
420                         javax.accessibility.AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
421                         null, ((javax.accessibility.Accessible) c).getAccessibleContext());
422                 }
423             }
424             public void componentRemoved(java.awt.event.ContainerEvent e) {
425                 java.awt.Component c = e.getChild();
426                 if (c != null && c instanceof javax.accessibility.Accessible) {
427                     AccessibleDialog.this.firePropertyChange(
428                         javax.accessibility.AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
429                         ((javax.accessibility.Accessible) c).getAccessibleContext(), null);
430                 }
431             }
432         }
433 
434         protected int propertyChangeListenerCount = 0;
435 
436         /**
437         * Add a PropertyChangeListener to the listener list.
438         *
439         * @param listener  The PropertyChangeListener to be added
440         */
441         public void addPropertyChangeListener(java.beans.PropertyChangeListener listener) {
442             if (propertyChangeListenerCount++ == 0) {
443                 accessibleWindowHandler = new AccessibleWindowHandler();
444                 Dialog.this.addWindowListener(accessibleWindowHandler);
445 
446                 accessibleContainerHandler = new AccessibleContainerHandler();
447                 Dialog.this.addContainerListener(accessibleContainerHandler);
448 
449                 accessibleComponentHandler = new AccessibleComponentHandler();
450                 Dialog.this.addComponentListener(accessibleComponentHandler);
451             }
452             super.addPropertyChangeListener(listener);
453         }
454 
455         /**
456         * Remove a PropertyChangeListener from the listener list.
457         * This removes a PropertyChangeListener that was registered
458         * for all properties.
459         *
460         * @param listener  The PropertyChangeListener to be removed
461         */
462         public void removePropertyChangeListener(java.beans.PropertyChangeListener listener) {
463             if (--propertyChangeListenerCount == 0) {
464                 Dialog.this.removeComponentListener(accessibleComponentHandler);
465                 accessibleComponentHandler = null;
466 
467                 Dialog.this.removeContainerListener(accessibleContainerHandler);
468                 accessibleContainerHandler = null;
469 
470                 Dialog.this.removeWindowListener(accessibleWindowHandler);
471                 accessibleWindowHandler = null;
472             }
473             super.removePropertyChangeListener(listener);
474         }
475 
476         /*
477         * AccessibleComponent
478         */
479 
480         /** Returns the background color of the object */
481         public java.awt.Color getBackground() {
482             try {
483                 return new java.awt.Color(unoAccessibleComponent.getBackground());
484             } catch (com.sun.star.uno.RuntimeException e) {
485                 return null;
486             }
487         }
488 
489         public void setBackground(java.awt.Color c) {
490             // Not supported by UNO accessibility API
491         }
492 
493         /** Returns the foreground color of the object */
494         public java.awt.Color getForeground() {
495             try {
496                 return new java.awt.Color(unoAccessibleComponent.getForeground());
497             } catch (com.sun.star.uno.RuntimeException e) {
498                 return null;
499             }
500         }
501 
502         public void setForeground(java.awt.Color c) {
503             // Not supported by UNO accessibility API
504         }
505 
506         public java.awt.Cursor getCursor() {
507             // Not supported by UNO accessibility API
508             return null;
509         }
510 
511         public void setCursor(java.awt.Cursor cursor) {
512             // Not supported by UNO accessibility API
513         }
514 
515         public java.awt.Font getFont() {
516             // FIXME
517             return null;
518         }
519 
520         public void setFont(java.awt.Font f) {
521             // Not supported by UNO accessibility API
522         }
523 
524         public java.awt.FontMetrics getFontMetrics(java.awt.Font f) {
525             // FIXME
526             return null;
527         }
528 
529         public boolean isEnabled() {
530             return Dialog.this.isEnabled();
531         }
532 
533         public void setEnabled(boolean b) {
534             // Not supported by UNO accessibility API
535         }
536 
537         public boolean isVisible() {
538             return Dialog.this.isVisible();
539         }
540 
541         public void setVisible(boolean b) {
542             // Not supported by UNO accessibility API
543         }
544 
545         public boolean isShowing() {
546             return Dialog.this.isShowing();
547         }
548 
549         public boolean contains(java.awt.Point p) {
550             try {
551                 return unoAccessibleComponent.containsPoint(new com.sun.star.awt.Point(p.x, p.y));
552             } catch (com.sun.star.uno.RuntimeException e) {
553                 return false;
554             }
555         }
556 
557         /** Returns the location of the object on the screen. */
558         public java.awt.Point getLocationOnScreen() {
559             try {
560                 com.sun.star.awt.Point unoPoint = unoAccessibleComponent.getLocationOnScreen();
561                 return new java.awt.Point(unoPoint.X, unoPoint.Y);
562             } catch (com.sun.star.uno.RuntimeException e) {
563                 return null;
564             }
565         }
566 
567         /** Gets the location of this component in the form of a point specifying the component's top-left corner */
568         public java.awt.Point getLocation() {
569             try {
570                 com.sun.star.awt.Point unoPoint = unoAccessibleComponent.getLocation();
571                 return new java.awt.Point( unoPoint.X, unoPoint.Y );
572             } catch (com.sun.star.uno.RuntimeException e) {
573                 return null;
574             }
575         }
576 
577         /** Moves this component to a new location */
578         public void setLocation(java.awt.Point p) {
579             // Not supported by UNO accessibility API
580         }
581 
582         /** Gets the bounds of this component in the form of a Rectangle object */
583         public java.awt.Rectangle getBounds() {
584             try {
585                 com.sun.star.awt.Rectangle unoRect = unoAccessibleComponent.getBounds();
586                 return new java.awt.Rectangle(unoRect.X, unoRect.Y, unoRect.Width, unoRect.Height);
587             } catch (com.sun.star.uno.RuntimeException e) {
588                 return null;
589             }
590         }
591 
592         /** Moves and resizes this component to conform to the new bounding rectangle r */
593         public void setBounds(java.awt.Rectangle r) {
594             // Not supported by UNO accessibility API
595         }
596 
597         /** Returns the size of this component in the form of a Dimension object */
598         public java.awt.Dimension getSize() {
599             try {
600                 com.sun.star.awt.Size unoSize = unoAccessibleComponent.getSize();
601                 return new java.awt.Dimension(unoSize.Width, unoSize.Height);
602             } catch (com.sun.star.uno.RuntimeException e) {
603                 return null;
604             }
605         }
606 
607         /** Resizes this component so that it has width d.width and height d.height */
608         public void setSize(java.awt.Dimension d) {
609             // Not supported by UNO accessibility API
610         }
611 
612         /** Returns the Accessible child, if one exists, contained at the local coordinate Point */
613         public javax.accessibility.Accessible getAccessibleAt(java.awt.Point p) {
614             try {
615                 java.awt.Component c = AccessibleObjectFactory.getAccessibleComponent(
616                     unoAccessibleComponent.getAccessibleAtPoint(new com.sun.star.awt.Point(p.x, p.y)));
617 
618                 return (javax.accessibility.Accessible) c;
619             } catch (com.sun.star.uno.RuntimeException e) {
620                 return null;
621             }
622         }
623 
624         public boolean isFocusTraversable() {
625             return Dialog.this.isFocusable();
626         }
627 
628         public void requestFocus() {
629             unoAccessibleComponent.grabFocus();
630         }
631     }
632 }
633 
634