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