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