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