/************************************************************************* * * $RCSfile: Window.java,v $ * * The Contents of this file are made available subject to the terms of * either of the following licenses * * - GNU Lesser General Public License Version 2.1 * - Sun Industry Standards Source License Version 1.1 * * Sun Microsystems Inc., October, 2000 * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2000 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * * Sun Industry Standards Source License Version 1.1 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.1 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://www.openoffice.org/license.html. * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2000 by Sun Microsystems, Inc. * * All Rights Reserved. * * Contributor(s): _______________________________________ * * ************************************************************************/ package org.openoffice.java.accessibility; import com.sun.star.uno.*; import com.sun.star.accessibility.*; public class Window extends java.awt.Window implements javax.accessibility.Accessible, NativeFrame { protected XAccessibleComponent unoAccessibleComponent; boolean opened = false; boolean visible = false; java.awt.EventQueue eventQueue = null; public Window(java.awt.Window owner, XAccessibleComponent xAccessibleComponent) { super(owner); initialize(xAccessibleComponent); } private void initialize(XAccessibleComponent xAccessibleComponent) { unoAccessibleComponent = xAccessibleComponent; eventQueue = java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue(); XAccessibleEventBroadcaster broadcaster = (XAccessibleEventBroadcaster) UnoRuntime.queryInterface(XAccessibleEventBroadcaster.class, unoAccessibleComponent); if (broadcaster != null) { broadcaster.addEventListener(new AccessibleWindowListener()); } } java.awt.Component initialComponent = null; public java.awt.Component getInitialComponent() { if (Build.DEBUG) { System.err.println("returning initial component object of class: " + initialComponent.getClass().getName()); } return initialComponent; } public void setInitialComponent(java.awt.Component c) { initialComponent = c; } public Integer getHWND() { return null; } /** * Determines whether this Component is showing on screen. * This means that the component must be visible, and it must be in a * container that is visible and showing. * @see #addNotify * @see #removeNotify * @since JDK1.0 */ public boolean isShowing() { if (isVisible()) { java.awt.Container parent = getParent(); return (parent == null) || parent.isShowing(); } return false; } /** * Makes this Component displayable by connecting it to a * native screen resource. * This method is called internally by the toolkit and should * not be called directly by programs. * @see #isDisplayable * @see #removeNotify * @since JDK1.0 */ public void addNotify() { // createHierarchyEvents(0, null, null, 0, false); } /** * Makes this Component undisplayable by destroying it native * screen resource. * This method is called by the toolkit internally and should * not be called directly by programs. * @see #isDisplayable * @see #addNotify * @since JDK1.0 */ public void removeNotify() { } /** * Determines if the object is visible. Note: this means that the * object intends to be visible; however, it may not in fact be * showing on the screen because one of the objects that this object * is contained by is not visible. To determine if an object is * showing on the screen, use isShowing. * * @return true if object is visible; otherwise, false */ public boolean isVisible(){ return visible; } /** * Shows or hides this component depending on the value of parameter * b. * @param b if true, shows this component; * otherwise, hides this component * @see #isVisible * @since JDK1.1 */ public void setVisible(boolean b) { if (visible != b){ visible = b; if (b) { // If it is the first show, fire WINDOW_OPENED event if (!opened) { postWindowEvent(java.awt.event.WindowEvent.WINDOW_OPENED); opened = true; } postComponentEvent(java.awt.event.ComponentEvent.COMPONENT_SHOWN); } else { postComponentEvent(java.awt.event.ComponentEvent.COMPONENT_HIDDEN); } } } public void dispose() { setVisible(false); postWindowEvent(java.awt.event.WindowEvent.WINDOW_CLOSED); } protected void postWindowEvent(int i) { eventQueue.postEvent(new java.awt.event.WindowEvent(this, i)); } protected void postComponentEvent(int i) { eventQueue.postEvent(new java.awt.event.ComponentEvent(this, i)); } /** * Update the proxy objects appropriatly on property change events */ protected class AccessibleWindowListener implements XAccessibleEventListener { protected AccessibleWindowListener() { } // The only expected state changes are ACTIVE and VISIBLE protected void setComponentState(short state, boolean enable) { switch (state) { case AccessibleStateType.ICONIFIED: postWindowEvent(enable ? java.awt.event.WindowEvent.WINDOW_ICONIFIED : java.awt.event.WindowEvent.WINDOW_DEICONIFIED); break; case AccessibleStateType.SHOWING: case AccessibleStateType.VISIBLE: setVisible(enable); break; default: if (Build.DEBUG) { // System.err.println("[frame]: " + getTitle() + "unexpected state change " + state); } break; } } /** Updates the accessible name and fires the appropriate PropertyChangedEvent */ protected void handleNameChangedEvent(Object any) { try { // Window.this.setTitle(AnyConverter.toString(any)); AnyConverter.toString(any); } catch (com.sun.star.lang.IllegalArgumentException e) { } } /** Updates the accessible description and fires the appropriate PropertyChangedEvent */ protected void handleDescriptionChangedEvent(Object any) { try { // This causes the property change event to be fired in the VCL thread // context. If this causes problems, it has to be deligated to the java // dispatch thread .. if (accessibleContext != null) { accessibleContext.setAccessibleDescription(AnyConverter.toString(any)); } } catch (com.sun.star.lang.IllegalArgumentException e) { } } /** Updates the internal states and fires the appropriate PropertyChangedEvent */ protected void handleStateChangedEvent(Object any1, Object any2) { try { if (AnyConverter.isShort(any1)) { setComponentState(AnyConverter.toShort(any1), false); } if (AnyConverter.isShort(any2)) { setComponentState(AnyConverter.toShort(any2), true); } } catch (com.sun.star.lang.IllegalArgumentException e) { } } /** Fires a visible data property change event */ protected void handleVisibleDataEvent() { javax.accessibility.AccessibleContext ac = accessibleContext; if (ac != null) { ac.firePropertyChange(javax.accessibility.AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, null, null); } } /** Called by OpenOffice process to notify property changes */ public void notifyEvent(AccessibleEventObject event) { switch (event.EventId) { case AccessibleEventId.NAME_CHANGED: // Set the accessible name for the corresponding context, which will fire a property // change event itself handleNameChangedEvent(event.NewValue); break; case AccessibleEventId.DESCRIPTION_CHANGED: // Set the accessible description for the corresponding context, which will fire a property // change event itself - so do not set propertyName ! handleDescriptionChangedEvent(event.NewValue); break; case AccessibleEventId.STATE_CHANGED: // Update the internal state set and fire the appropriate PropertyChangedEvent handleStateChangedEvent(event.OldValue, event.NewValue); break; case AccessibleEventId.CHILD: if (AnyConverter.isObject(event.OldValue)) { AccessibleObjectFactory.removeChild(Window.this, event.OldValue); } else if (AnyConverter.isObject(event.NewValue)) { AccessibleObjectFactory.addChild(Window.this, event.NewValue); } break; case AccessibleEventId.VISIBLE_DATA_CHANGED: case AccessibleEventId.BOUNDRECT_CHANGED: handleVisibleDataEvent(); break; default: // Warn about unhandled events if(Build.DEBUG) { System.out.println(this + ": unhandled accessibility event id=" + event.EventId); } } } /** Called by OpenOffice process to notify that the UNO component is disposing */ public void disposing(com.sun.star.lang.EventObject eventObject) { } } protected javax.accessibility.AccessibleContext accessibleContext = null; /** Returns the AccessibleContext associated with this object */ public javax.accessibility.AccessibleContext getAccessibleContext() { if (accessibleContext == null) { accessibleContext = new AccessibleWindow(); // accessibleContext.setAccessibleName(getTitle()); } return accessibleContext; } protected class AccessibleWindow extends java.awt.Window.AccessibleAWTWindow { protected AccessibleWindow() { super(); } protected java.awt.event.ComponentListener accessibleComponentHandler = null; /** * Fire PropertyChange listener, if one is registered, * when shown/hidden.. */ protected class AccessibleComponentHandler implements java.awt.event.ComponentListener { public void componentHidden(java.awt.event.ComponentEvent e) { AccessibleWindow.this.firePropertyChange( javax.accessibility.AccessibleContext.ACCESSIBLE_STATE_PROPERTY, javax.accessibility.AccessibleState.VISIBLE, null); } public void componentShown(java.awt.event.ComponentEvent e) { AccessibleWindow.this.firePropertyChange( javax.accessibility.AccessibleContext.ACCESSIBLE_STATE_PROPERTY, null, javax.accessibility.AccessibleState.VISIBLE); } public void componentMoved(java.awt.event.ComponentEvent e) { } public void componentResized(java.awt.event.ComponentEvent e) { } } // inner class AccessibleComponentHandler protected java.awt.event.ContainerListener accessibleContainerHandler = null; /** * Fire PropertyChange listener, if one is registered, * when children added/removed. */ protected class AccessibleContainerHandler implements java.awt.event.ContainerListener { public void componentAdded(java.awt.event.ContainerEvent e) { java.awt.Component c = e.getChild(); if (c != null && c instanceof javax.accessibility.Accessible) { AccessibleWindow.this.firePropertyChange( javax.accessibility.AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, null, ((javax.accessibility.Accessible) c).getAccessibleContext()); } } public void componentRemoved(java.awt.event.ContainerEvent e) { java.awt.Component c = e.getChild(); if (c != null && c instanceof javax.accessibility.Accessible) { AccessibleWindow.this.firePropertyChange( javax.accessibility.AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, ((javax.accessibility.Accessible) c).getAccessibleContext(), null); } } } protected int propertyChangeListenerCount = 0; /** * Add a PropertyChangeListener to the listener list. * * @param listener The PropertyChangeListener to be added */ public void addPropertyChangeListener(java.beans.PropertyChangeListener listener) { if (propertyChangeListenerCount++ == 0) { accessibleContainerHandler = new AccessibleContainerHandler(); Window.this.addContainerListener(accessibleContainerHandler); accessibleComponentHandler = new AccessibleComponentHandler(); Window.this.addComponentListener(accessibleComponentHandler); } super.addPropertyChangeListener(listener); } /** * Remove a PropertyChangeListener from the listener list. * This removes a PropertyChangeListener that was registered * for all properties. * * @param listener The PropertyChangeListener to be removed */ public void removePropertyChangeListener(java.beans.PropertyChangeListener listener) { if (--propertyChangeListenerCount == 0) { Window.this.removeComponentListener(accessibleComponentHandler); accessibleComponentHandler = null; Window.this.removeContainerListener(accessibleContainerHandler); accessibleContainerHandler = null; } super.removePropertyChangeListener(listener); } /* * AccessibleComponent */ /** Returns the background color of the object */ public java.awt.Color getBackground() { try { return new java.awt.Color(unoAccessibleComponent.getBackground()); } catch (com.sun.star.uno.RuntimeException e) { return null; } } public void setBackground(java.awt.Color c) { // Not supported by UNO accessibility API } /** Returns the foreground color of the object */ public java.awt.Color getForeground() { try { return new java.awt.Color(unoAccessibleComponent.getForeground()); } catch (com.sun.star.uno.RuntimeException e) { return null; } } public void setForeground(java.awt.Color c) { // Not supported by UNO accessibility API } public java.awt.Cursor getCursor() { // Not supported by UNO accessibility API return null; } public void setCursor(java.awt.Cursor cursor) { // Not supported by UNO accessibility API } public java.awt.Font getFont() { // FIXME return null; } public void setFont(java.awt.Font f) { // Not supported by UNO accessibility API } public java.awt.FontMetrics getFontMetrics(java.awt.Font f) { // FIXME return null; } public boolean isEnabled() { return Window.this.isEnabled(); } public void setEnabled(boolean b) { // Not supported by UNO accessibility API } public boolean isVisible() { return Window.this.isVisible(); } public void setVisible(boolean b) { // Not supported by UNO accessibility API } public boolean isShowing() { return Window.this.isShowing(); } public boolean contains(java.awt.Point p) { try { return unoAccessibleComponent.containsPoint(new com.sun.star.awt.Point(p.x, p.y)); } catch (com.sun.star.uno.RuntimeException e) { return false; } } /** Returns the location of the object on the screen. */ public java.awt.Point getLocationOnScreen() { try { com.sun.star.awt.Point unoPoint = unoAccessibleComponent.getLocationOnScreen(); return new java.awt.Point(unoPoint.X, unoPoint.Y); } catch (com.sun.star.uno.RuntimeException e) { return null; } } /** Gets the location of this component in the form of a point specifying the component's top-left corner */ public java.awt.Point getLocation() { try { com.sun.star.awt.Point unoPoint = unoAccessibleComponent.getLocation(); return new java.awt.Point( unoPoint.X, unoPoint.Y ); } catch (com.sun.star.uno.RuntimeException e) { return null; } } /** Moves this component to a new location */ public void setLocation(java.awt.Point p) { // Not supported by UNO accessibility API } /** Gets the bounds of this component in the form of a Rectangle object */ public java.awt.Rectangle getBounds() { try { com.sun.star.awt.Rectangle unoRect = unoAccessibleComponent.getBounds(); return new java.awt.Rectangle(unoRect.X, unoRect.Y, unoRect.Width, unoRect.Height); } catch (com.sun.star.uno.RuntimeException e) { return null; } } /** Moves and resizes this component to conform to the new bounding rectangle r */ public void setBounds(java.awt.Rectangle r) { // Not supported by UNO accessibility API } /** Returns the size of this component in the form of a Dimension object */ public java.awt.Dimension getSize() { try { com.sun.star.awt.Size unoSize = unoAccessibleComponent.getSize(); return new java.awt.Dimension(unoSize.Width, unoSize.Height); } catch (com.sun.star.uno.RuntimeException e) { return null; } } /** Resizes this component so that it has width d.width and height d.height */ public void setSize(java.awt.Dimension d) { // Not supported by UNO accessibility API } /** Returns the Accessible child, if one exists, contained at the local coordinate Point */ public javax.accessibility.Accessible getAccessibleAt(java.awt.Point p) { try { java.awt.Component c = AccessibleObjectFactory.getAccessibleComponent( unoAccessibleComponent.getAccessibleAtPoint(new com.sun.star.awt.Point(p.x, p.y))); return (javax.accessibility.Accessible) c; } catch (com.sun.star.uno.RuntimeException e) { return null; } } public boolean isFocusTraversable() { return Window.this.isFocusable(); } public void requestFocus() { unoAccessibleComponent.grabFocus(); } } }