summaryrefslogtreecommitdiff
path: root/odk/examples/DevelopersGuide/Accessibility
diff options
context:
space:
mode:
Diffstat (limited to 'odk/examples/DevelopersGuide/Accessibility')
-rw-r--r--odk/examples/DevelopersGuide/Accessibility/ConnectionTask.java208
-rw-r--r--odk/examples/DevelopersGuide/Accessibility/EventHandler.java447
-rw-r--r--odk/examples/DevelopersGuide/Accessibility/EventListenerProxy.java232
-rw-r--r--odk/examples/DevelopersGuide/Accessibility/GraphicalDisplay.java189
-rw-r--r--odk/examples/DevelopersGuide/Accessibility/IAccessibleObjectDisplay.java46
-rw-r--r--odk/examples/DevelopersGuide/Accessibility/Makefile113
-rw-r--r--odk/examples/DevelopersGuide/Accessibility/MessageArea.java133
-rw-r--r--odk/examples/DevelopersGuide/Accessibility/NameProvider.java290
-rw-r--r--odk/examples/DevelopersGuide/Accessibility/RegistrationThread.java156
-rw-r--r--odk/examples/DevelopersGuide/Accessibility/SSR.java171
-rw-r--r--odk/examples/DevelopersGuide/Accessibility/TextualDisplay.java230
-rw-r--r--odk/examples/DevelopersGuide/Accessibility/makefile.mk73
12 files changed, 2288 insertions, 0 deletions
diff --git a/odk/examples/DevelopersGuide/Accessibility/ConnectionTask.java b/odk/examples/DevelopersGuide/Accessibility/ConnectionTask.java
new file mode 100644
index 000000000000..7bf9bdb88cd5
--- /dev/null
+++ b/odk/examples/DevelopersGuide/Accessibility/ConnectionTask.java
@@ -0,0 +1,208 @@
+/*************************************************************************
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the BSD license.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *************************************************************************/
+
+import java.awt.event.ActionListener;
+import javax.swing.*;
+import java.awt.*;
+import java.util.*;
+
+import com.sun.star.awt.XFocusListener;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.bridge.XUnoUrlResolver;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.accessibility.*;
+import com.sun.star.awt.XExtendedToolkit;
+
+
+/** This timer task tries to connect to a running Office application in regular
+ intervals until a connection can be successfully established.
+*/
+class ConnectionTask
+ extends TimerTask
+{
+ public ConnectionTask (EventListenerProxy xListener)
+ {
+ Init (xListener);
+ }
+
+ private void Init (EventListenerProxy xListener)
+ {
+ mxListener = xListener;
+ mbInitialized = false;
+
+ maTimer = new java.util.Timer ();
+ maTimer.schedule (this, 0, mnPeriod);
+ }
+
+
+ /** This method is run every time the task is executed. It tries to
+ connect to and register the listener at an Office application. If it
+ can establish a connection it terminates the timer task. Otherwise it
+ waits until the next activation.
+ */
+ public void run ()
+ {
+ if (registerListeners())
+ {
+ // Focus listener was successfully registered so we can cancel this task.
+ MessageArea.println ("\nconnected successfully to office");
+ cancel ();
+ maTimer = null;
+ }
+ }
+
+
+
+
+ /** Try to register the listener.
+ */
+ private boolean registerListeners ()
+ {
+ // Get toolkit.
+ XExtendedToolkit xToolkit = getToolkit ();
+
+ // Register at toolkit as focus event listener.
+ if (xToolkit != null)
+ {
+ xToolkit.addTopWindowListener (mxListener);
+ int nTopWindowCount = xToolkit.getTopWindowCount();
+ try
+ {
+ com.sun.star.lang.EventObject aEvent = new com.sun.star.lang.EventObject();
+ for (int i=0; i<nTopWindowCount; i++)
+ {
+ XAccessible xAccessible = (XAccessible) UnoRuntime.queryInterface(
+ XAccessible.class,
+ xToolkit.getTopWindow(i));
+ XAccessibleContext xContext = xAccessible.getAccessibleContext();
+ if (xContext.getAccessibleName().length() > 0)
+ {
+ // Simulate an event that leads to registration the
+ // listener at the window.
+ aEvent.Source = xToolkit.getTopWindow(i);
+ mxListener.windowOpened (aEvent);
+ }
+ }
+ }
+
+ catch (com.sun.star.lang.IndexOutOfBoundsException aException)
+ {
+ // This exception signals that the number of top windows has
+ // changed since our last call to getTopWindowCount().
+ }
+ return true;
+ }
+ else
+ return false;
+ }
+
+
+
+
+ /** Get the toolkit from an Office which can then be used to register
+ the listener.
+ */
+ private XExtendedToolkit getToolkit ()
+ {
+ XMultiServiceFactory xFactory = connectToOffice();
+
+ // Get toolkit.
+ XExtendedToolkit xToolkit = null;
+ try
+ {
+ if (xFactory != null)
+ {
+ xToolkit = (XExtendedToolkit) UnoRuntime.queryInterface(
+ XExtendedToolkit.class,
+ xFactory.createInstance ("stardiv.Toolkit.VCLXToolkit"));
+ }
+ }
+ catch (com.sun.star.uno.Exception aException)
+ {
+ MessageArea.println ("caught exception while creating extended toolkit");
+ // Ignored.
+ }
+
+ return xToolkit;
+ }
+
+
+
+
+ /** Connect to a running (Star|Open)Office application
+ */
+ private XMultiServiceFactory connectToOffice ()
+ {
+ // connect to a running office and get the ServiceManager
+ try
+ {
+ com.sun.star.uno.XComponentContext xCmpContext = null;
+
+ // get the remote office component context
+ xCmpContext = com.sun.star.comp.helper.Bootstrap.bootstrap();
+ if( xCmpContext != null )
+ System.out.println("Connected to a running office ...");
+
+ // get the remote office service manager
+ com.sun.star.lang.XMultiComponentFactory xMCF =
+ xCmpContext.getServiceManager();
+
+ return (XMultiServiceFactory) UnoRuntime.queryInterface (
+ XMultiServiceFactory.class, xMCF);
+ }
+
+ catch (Exception e)
+ {
+ if ( ! mbInitialized)
+ MessageArea.println ("Could not connect to office");
+ else
+ MessageArea.print (".");
+ }
+ mbInitialized = true;
+ return null;
+ }
+
+ /** Time in milliseconds between two attempts to connect to an Office
+ application.
+ */
+ private int mnPeriod = 1000;
+
+ private EventListenerProxy mxListener;
+ private boolean mbInitialized;
+
+ /** This timer is used for the registration loop to retry to connect to
+ the Office until a connection can be established.
+ */
+ private java.util.Timer maTimer;
+}
diff --git a/odk/examples/DevelopersGuide/Accessibility/EventHandler.java b/odk/examples/DevelopersGuide/Accessibility/EventHandler.java
new file mode 100644
index 000000000000..61395bba7d70
--- /dev/null
+++ b/odk/examples/DevelopersGuide/Accessibility/EventHandler.java
@@ -0,0 +1,447 @@
+/*************************************************************************
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the BSD license.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *************************************************************************/
+
+import java.util.Vector;
+
+import com.sun.star.uno.AnyConverter;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.Type;
+import com.sun.star.accessibility.*;
+
+/** Handle all the events send from accessibility objects. The events
+ denoting new or removed top windows are handled as well.
+
+ It does not implement any listener interface as does the
+ EventListenerProxy class because it is interested only in a sub set of
+ the event types.
+*/
+public class EventHandler
+{
+ public EventHandler ()
+ {
+ mnTopWindowCount = 0;
+ maListenerProxy = new EventListenerProxy (this);
+ maConnectionTask = new ConnectionTask (maListenerProxy);
+ maObjectDisplays = new Vector ();
+ }
+
+ public synchronized void addObjectDisplay (IAccessibleObjectDisplay aDisplay)
+ {
+ maObjectDisplays.add (aDisplay);
+ }
+
+
+ public void finalize ()
+ {
+ // When it is running then cancel the timer that tries to connect to
+ // the Office.
+ if (maConnectionTask != null)
+ maConnectionTask.cancel();
+ }
+
+
+
+ public void disposing (com.sun.star.lang.EventObject aEvent)
+ {
+ // Ignored: We are not holding references to accessibility objects.
+ }
+
+
+
+
+ /** This method is called back when a new top level window has been opened.
+ */
+ public void windowOpened (XAccessible xAccessible)
+ {
+ if (xAccessible != null)
+ {
+ // Update the counter of currently open top level windows
+ // observed by this object.
+ mnTopWindowCount += 1;
+
+ XAccessibleContext xContext = xAccessible.getAccessibleContext();
+ if (xContext != null)
+ {
+ MessageArea.println ("new top level window has accessible name "
+ + xContext.getAccessibleName());
+
+ // Register at all accessible objects of the new window.
+ new RegistrationThread (
+ maListenerProxy,
+ xContext,
+ true,
+ true);
+ }
+ else
+ MessageArea.println ("new top level window is not accessible.");
+ }
+ else
+ MessageArea.println ("new top level window is not accessible.");
+ }
+
+
+
+
+ public void windowClosed (XAccessible xAccessible)
+ {
+ mnTopWindowCount -= 1;
+ MessageArea.println ("window closed, " + mnTopWindowCount + " still open");
+ if (mnTopWindowCount == 0)
+ {
+ // This was the last window. Wait for a new connection.
+ MessageArea.println ("lost connection to office");
+ new ConnectionTask (maListenerProxy);
+ }
+ if (xAccessible != null)
+ new RegistrationThread (
+ maListenerProxy,
+ xAccessible.getAccessibleContext(),
+ false,
+ true);
+ }
+
+
+
+
+ /** Print a message that the given object just received the focus. Call
+ all accessible object diplays and tell them to update.
+ */
+ private synchronized void focusGained (XAccessibleContext xContext)
+ {
+ if (xContext != null)
+ {
+ MessageArea.println ("focusGained: " + xContext.getAccessibleName()
+ + " with role "
+ + NameProvider.getRoleName (xContext.getAccessibleRole()));
+
+ // Tell the object displays to update their views.
+ for (int i=0; i<maObjectDisplays.size(); i++)
+ {
+ IAccessibleObjectDisplay aDisplay =
+ (IAccessibleObjectDisplay)maObjectDisplays.get(i);
+ if (aDisplay != null)
+ aDisplay.setAccessibleObject (xContext);
+ }
+
+ // Remember the currently focused object.
+ mxFocusedObject = xContext;
+ }
+ else
+ MessageArea.println ("focusGained: null");
+ }
+
+
+
+
+ /** Print a message that the given object just lost the focus. Call
+ all accessible object diplays and tell them to update.
+ */
+ private synchronized void focusLost (XAccessibleContext xContext)
+ {
+ if (xContext != null)
+ {
+ MessageArea.println ("focusLost: "
+ + xContext.getAccessibleName()
+ + " with role "
+ + NameProvider.getRoleName (xContext.getAccessibleRole()));
+
+ // Tell the object displays to update their views.
+ for (int i=0; i<maObjectDisplays.size(); i++)
+ {
+ IAccessibleObjectDisplay aDisplay =
+ (IAccessibleObjectDisplay)maObjectDisplays.get(i);
+ if (aDisplay != null)
+ aDisplay.setAccessibleObject (null);
+ }
+ mxFocusedObject = null;
+ }
+ else
+ MessageArea.println ("focusLost: null");
+ }
+
+
+
+
+ /** Handle a change of the caret position. Ignore this on all objects
+ but the one currently focused.
+ */
+ private void handleCaretEvent (XAccessibleContext xContext,
+ long nOldPosition, long nNewPosition)
+ {
+ if (xContext == mxFocusedObject)
+ MessageArea.println ("caret moved from " + nOldPosition + " to " + nNewPosition);
+ }
+
+
+
+
+ /** Print a message that a state has been changed.
+ @param xContext
+ The accessible context of the object whose state has changed.
+ @param nOldState
+ When not zero then this value describes a state that has been reset.
+ @param nNewValue
+ When not zero then this value describes a state that has been set.
+ */
+ private void handleStateChange (XAccessibleContext xContext, short nOldState, short nNewState)
+ {
+ // Determine which state has changed and what is its new value.
+ short nState;
+ boolean aNewValue;
+ if (nOldState >= 0)
+ {
+ nState = nOldState;
+ aNewValue = false;
+ }
+ else
+ {
+ nState = nNewState;
+ aNewValue = true;
+ }
+
+ // Print a message about the changed state.
+ MessageArea.print ("setting state " + NameProvider.getStateName(nState)
+ + " to " + aNewValue);
+ if (xContext != null)
+ {
+ MessageArea.println (" at " + xContext.getAccessibleName() + " with role "
+ + NameProvider.getRoleName(xContext.getAccessibleRole()));
+ }
+ else
+ MessageArea.println (" at null");
+
+ // Further handling of some states
+ switch (nState)
+ {
+ case AccessibleStateType.FOCUSED:
+ if (aNewValue)
+ focusGained (xContext);
+ else
+ focusLost (xContext);
+ }
+ }
+
+
+
+
+ /** Handle a child event that describes the creation of removal of a
+ single child.
+ */
+ private void handleChildEvent (
+ XAccessibleContext aOldChild,
+ XAccessibleContext aNewChild)
+ {
+ if (aOldChild != null)
+ // Remove event listener from the child and all of its descendants.
+ new RegistrationThread (maListenerProxy, aOldChild, false, false);
+ else if (aNewChild != null)
+ // Add event listener to the new child and all of its descendants.
+ new RegistrationThread (maListenerProxy, aNewChild, true, false);
+ }
+
+
+
+
+ /** Handle the change of some visible data of an object.
+ */
+ private void handleVisibleDataEvent (XAccessibleContext xContext)
+ {
+ // The given object may affect the visible appearance of the focused
+ // object even when the two are not identical when the given object
+ // is an ancestor of the focused object.
+ // In order to not check this we simply call an update on the
+ // focused object.
+ if (mxFocusedObject != null)
+ for (int i=0; i<maObjectDisplays.size(); i++)
+ {
+ IAccessibleObjectDisplay aDisplay =
+ (IAccessibleObjectDisplay)maObjectDisplays.get(i);
+ if (aDisplay != null)
+ aDisplay.updateAccessibleObject (mxFocusedObject);
+ }
+ }
+
+
+
+
+ /** Print some information about an event that is not handled by any
+ more specialized handler.
+ */
+ private void handleGenericEvent (
+ int nEventId,
+ Object aSource,
+ Object aOldValue,
+ Object aNewValue)
+ {
+ // Print event to message area.
+ MessageArea.print ("received event "
+ + NameProvider.getEventName (nEventId) + " from ");
+ XAccessibleContext xContext = objectToContext (aSource);
+ if (xContext != null)
+ MessageArea.print (xContext.getAccessibleName());
+ else
+ MessageArea.print ("null");
+ MessageArea.println (" / "
+ + NameProvider.getRoleName(xContext.getAccessibleRole()));
+ }
+
+
+
+ /** This is the main method for handling accessibility events. It is
+ assumed that it is not called directly from the Office but from a
+ listener proxy that runs in a separate thread so that calls back to
+ the Office do not result in dead-locks.
+ */
+ public void notifyEvent (com.sun.star.accessibility.AccessibleEventObject aEvent)
+ {
+ try // Guard against disposed objects.
+ {
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId.CHILD:
+ handleChildEvent (
+ objectToContext (aEvent.OldValue),
+ objectToContext (aEvent.NewValue));
+ break;
+
+ case AccessibleEventId.STATE_CHANGED:
+ {
+ short nOldState = -1;
+ short nNewState = -1;
+ try
+ {
+ if (AnyConverter.isShort (aEvent.NewValue))
+ nNewState = AnyConverter.toShort (aEvent.NewValue);
+ if (AnyConverter.isShort (aEvent.OldValue))
+ nOldState = AnyConverter.toShort (aEvent.OldValue);
+ }
+ catch (com.sun.star.lang.IllegalArgumentException e)
+ {}
+ handleStateChange (
+ objectToContext (aEvent.Source),
+ nOldState,
+ nNewState);
+ }
+ break;
+
+ case AccessibleEventId.VISIBLE_DATA_CHANGED:
+ case AccessibleEventId.BOUNDRECT_CHANGED:
+ handleVisibleDataEvent (objectToContext (aEvent.Source));
+ break;
+
+ case AccessibleEventId.CARET_CHANGED:
+ try
+ {
+ handleCaretEvent (
+ objectToContext (aEvent.Source),
+ AnyConverter.toLong(aEvent.OldValue),
+ AnyConverter.toLong(aEvent.NewValue));
+ }
+ catch (com.sun.star.lang.IllegalArgumentException e)
+ {}
+ break;
+
+ default:
+ handleGenericEvent (aEvent.EventId,
+ aEvent.Source, aEvent.OldValue, aEvent.NewValue);
+ break;
+ }
+ }
+ catch (com.sun.star.lang.DisposedException e)
+ {}
+ }
+
+
+
+
+ /** Convert the given object into an accessible context. The object is
+ interpreted as UNO Any and may contain either an XAccessible or
+ XAccessibleContext reference.
+ @return
+ The returned value is null when the given object can not be
+ converted to an XAccessibleContext reference.
+ */
+ private XAccessibleContext objectToContext (Object aObject)
+ {
+ XAccessibleContext xContext = null;
+ XAccessible xAccessible = null;
+ try
+ {
+ xAccessible = (XAccessible)AnyConverter.toObject(
+ new Type(XAccessible.class), aObject);
+ }
+ catch (com.sun.star.lang.IllegalArgumentException e)
+ {}
+ if (xAccessible != null)
+ xContext = xAccessible.getAccessibleContext();
+ else
+ try
+ {
+ xContext = (XAccessibleContext)AnyConverter.toObject(
+ new Type(XAccessibleContext.class), aObject);
+ }
+ catch (com.sun.star.lang.IllegalArgumentException e)
+ {}
+ return xContext;
+ }
+
+
+
+
+ /** The proxy that runs in a seperate thread and allows to call back to
+ the Office without running into dead-locks.
+ */
+ private EventListenerProxy maListenerProxy;
+
+ /** The currently focused object. A value of null means that no object
+ has the focus.
+ */
+ private XAccessibleContext mxFocusedObject;
+
+ /** Keep track of the currently open top windows to start a registration
+ loop when the last window (and the Office) is closed.
+ */
+ private long mnTopWindowCount;
+
+ /** A list of objects that can display accessible objects in specific
+ ways such as showing a graphical representation or some textual
+ descriptions.
+ */
+ private Vector maObjectDisplays;
+
+ /** The timer task that attempts in regular intervals to connect to a
+ running Office application.
+ */
+ private ConnectionTask maConnectionTask;
+}
diff --git a/odk/examples/DevelopersGuide/Accessibility/EventListenerProxy.java b/odk/examples/DevelopersGuide/Accessibility/EventListenerProxy.java
new file mode 100644
index 000000000000..273f6146a6cc
--- /dev/null
+++ b/odk/examples/DevelopersGuide/Accessibility/EventListenerProxy.java
@@ -0,0 +1,232 @@
+/*************************************************************************
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the BSD license.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *************************************************************************/
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleEventListener;
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.lang.EventObject;
+import com.sun.star.awt.XTopWindowListener;
+import com.sun.star.uno.UnoRuntime;
+
+import java.util.LinkedList;
+
+/** This class acts as a proxy for the simple screen reader. It waits for
+ two types of events:
+ 1. Accessibility events signal modifications concerning accessibility
+ objects.
+ 2. Top window events inform the listener about new or removed windows.
+
+ This class exists because events had to be handled in a seperate thread
+ to avoid dead locks: The thread that receives an event must no call back
+ to the Office directly.
+
+ Soon this should not be necessary anymore. There is now a flag which
+ switches between synchronous and asynchronous callbacks.
+
+ All reveived events are eventually forwarded to the actual listener. In
+ this way it decouples the Office from the listener.
+*/
+class EventListenerProxy
+ implements Runnable, XAccessibleEventListener, XTopWindowListener
+{
+ public EventListenerProxy (EventHandler aListener)
+ {
+ maListener = aListener;
+ mbAsynchron = true;
+ if (mbAsynchron)
+ {
+ maEventQueue = new LinkedList();
+ new Thread (this, "EventListenerProxy").start();
+ }
+ }
+
+ private void addEvent (Runnable aEventObject)
+ {
+ if (mbAsynchron)
+ synchronized (maEventQueue)
+ {
+ maEventQueue.addLast (aEventObject);
+ // Tell the queue that there is a new event in the queue.
+ maEventQueue.notify();
+ }
+ else
+ {
+ System.out.println ("running " + aEventObject);
+ aEventObject.run();
+ System.out.println (" done");
+ }
+ }
+
+
+
+
+ /** In an infinite loop, check for events to deliver, then wait on lock
+ (which will be notified when new events arrive)
+ */
+ public void run ()
+ {
+ while (true)
+ {
+ // Process all events that are currently in the queue.
+ Runnable aEvent;
+ do
+ {
+ synchronized (maEventQueue)
+ {
+ if (maEventQueue.size() > 0)
+ aEvent = (Runnable)maEventQueue.removeFirst();
+ else
+ aEvent = null;
+ }
+
+ if (aEvent != null)
+ {
+ try
+ {
+ aEvent.run();
+ }
+ catch (Throwable aException)
+ {
+ MessageArea.println(
+ "Exception during event delivery: " + aException);
+ aException.printStackTrace();
+ }
+ }
+ }
+ while (aEvent != null);
+
+ // Now that the queue is empty go to sleep again.
+ try
+ {
+ synchronized (maEventQueue)
+ {
+ maEventQueue.wait();
+ }
+ }
+ catch (Exception aException)
+ {
+ // Ignore this exception since there is not much
+ // that we can do about it.
+ }
+ }
+ }
+
+
+ public void disposing( final EventObject aEvent)
+ {
+ addEvent (new Runnable()
+ {
+ public void run()
+ {
+ maListener.disposing (aEvent);
+ }
+ } );
+ }
+
+ public void notifyEvent (final AccessibleEventObject aEvent)
+ {
+ addEvent (
+ new Runnable()
+ {
+ public void run()
+ {
+ maListener.notifyEvent (aEvent);
+ }
+ } );
+ }
+
+ public void windowOpened (final com.sun.star.lang.EventObject aEvent)
+ {
+ addEvent (
+ new Runnable()
+ {
+ public void run()
+ {
+ maListener.windowOpened (
+ (XAccessible) UnoRuntime.queryInterface(
+ XAccessible.class,
+ aEvent.Source));
+ }
+ } );
+ }
+ public void windowClosing (final com.sun.star.lang.EventObject aEvent)
+ {
+ // Ignored.
+ }
+ public void windowClosed (final com.sun.star.lang.EventObject aEvent)
+ {
+ addEvent (
+ new Runnable()
+ {
+ public void run()
+ {
+ maListener.windowClosed (
+ (XAccessible) UnoRuntime.queryInterface(
+ XAccessible.class,
+ aEvent.Source));
+ }
+ } );
+ }
+ public void windowMinimized (com.sun.star.lang.EventObject aEvent)
+ {
+ // Ignored.
+ }
+ public void windowNormalized (com.sun.star.lang.EventObject aEvent)
+ {
+ // Ignored.
+ }
+ public void windowActivated (com.sun.star.lang.EventObject aEvent)
+ {
+ // Ignored.
+ }
+ public void windowDeactivated (com.sun.star.lang.EventObject aEvent)
+ {
+ // Ignored.
+ }
+
+ /** The queue of event objects, LinkedList<Runnable>.
+ The queue object will also serve as lock for the consumer/producer type
+ syncronization.
+ */
+ private LinkedList maEventQueue;
+
+ /** This is the actual listener that the events will eventually forwarded to.
+ */
+ private EventHandler maListener;
+
+ /** This flag determines whether event forwarding is done asynchroniously
+ or synchroniously.
+ */
+ private boolean mbAsynchron;
+}
diff --git a/odk/examples/DevelopersGuide/Accessibility/GraphicalDisplay.java b/odk/examples/DevelopersGuide/Accessibility/GraphicalDisplay.java
new file mode 100644
index 000000000000..37579e1c3242
--- /dev/null
+++ b/odk/examples/DevelopersGuide/Accessibility/GraphicalDisplay.java
@@ -0,0 +1,189 @@
+/*************************************************************************
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the BSD license.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *************************************************************************/
+
+import javax.swing.*;
+import java.awt.Dimension;
+import java.awt.*;
+import java.awt.geom.*;
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleComponent;
+
+import com.sun.star.awt.Point;
+import com.sun.star.awt.Size;
+import com.sun.star.uno.UnoRuntime;
+
+
+/** Display the currently focused accessible object graphically.
+*/
+public class GraphicalDisplay
+ extends JPanel
+ implements IAccessibleObjectDisplay
+{
+ /** Create a new graphical widget the displays some of the geometrical
+ information availbable from accessible objects.
+ */
+ public GraphicalDisplay ()
+ {
+ setPreferredSize (new Dimension (300,200));
+ }
+
+
+ /** Paint some or all of the area of this widget with the outlines of
+ the currently focues object and its ancestors.
+ */
+ public synchronized void paintComponent (Graphics g)
+ {
+ super.paintComponent (g);
+
+ setupTransformation ();
+
+ // Draw the screen representation to give a hint of the location of the
+ // accessible object on the screen.
+ Dimension aScreenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ // Fill the screen rectangle.
+ g.setColor (new Color (250,240,230));
+ g.fillRect (
+ (int)(mnHOffset+0.5),
+ (int)(mnVOffset+0.5),
+ (int)(mnScale*aScreenSize.getWidth()),
+ (int)(mnScale*aScreenSize.getHeight()));
+ // Draw a frame arround the screen rectangle to increase its visibility.
+ g.setColor (Color.BLACK);
+ g.drawRect (
+ (int)(mnHOffset+0.5),
+ (int)(mnVOffset+0.5),
+ (int)(mnScale*aScreenSize.getWidth()),
+ (int)(mnScale*aScreenSize.getHeight()));
+
+ // Now do the actual display of the accessible object.
+ drawAccessibleObject (g, mxContext, Color.GREEN);
+ }
+ public synchronized void paintChildren (Graphics g)
+ {
+ }
+ public synchronized void paintBorder (Graphics g)
+ {
+ }
+
+
+
+
+ /** Draw a simple representation of the given accessible object in the
+ specified color.
+ */
+ public void drawAccessibleObject (Graphics g, XAccessibleContext xContext, Color aColor)
+ {
+ if (xContext != null)
+ {
+ // First draw our parent.
+ XAccessible xParent = xContext.getAccessibleParent();
+ if (xParent != null)
+ drawAccessibleObject (g, xParent.getAccessibleContext(), Color.GRAY);
+
+ // When the context supports the XAccessibleComponent interface
+ // then draw its outline.
+ XAccessibleComponent xComponent =
+ (XAccessibleComponent)UnoRuntime.queryInterface(
+ XAccessibleComponent.class, xContext);
+ if (xComponent != null)
+ {
+ // Get size and location on screen and transform them to fit
+ // everything inside this widget.
+ Point aLocation = xComponent.getLocationOnScreen();
+ Size aSize = xComponent.getSize();
+ g.setColor (aColor);
+ g.drawRect (
+ (int)(mnHOffset + mnScale*aLocation.X+0.5),
+ (int)(mnVOffset + mnScale*aLocation.Y+0.5),
+ (int)(mnScale*aSize.Width),
+ (int)(mnScale*aSize.Height));
+ }
+ }
+ }
+
+
+ public synchronized void setAccessibleObject (XAccessibleContext xContext)
+ {
+ mxContext = xContext;
+ repaint ();
+ }
+
+ public synchronized void updateAccessibleObject (XAccessibleContext xContext)
+ {
+ repaint ();
+ }
+
+
+ /** Set up the transformation so that the graphical display can show a
+ centered representation of the whole screen.
+ */
+ private void setupTransformation ()
+ {
+ Dimension aScreenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ Dimension aWidgetSize = getSize();
+ if ((aScreenSize.getWidth() > 0) && (aScreenSize.getHeight() > 0))
+ {
+ // Calculate the scales that would map the screen onto the
+ // widget in both of the coordinate axes and select the smaller
+ // of the two: it maps the screen onto the widget in both axes
+ // at the same time.
+ double nHScale = (aWidgetSize.getWidth() - 10) / aScreenSize.getWidth();
+ double nVScale = (aWidgetSize.getHeight() - 10) / aScreenSize.getHeight();
+ if (nHScale < nVScale)
+ mnScale = nHScale;
+ else
+ mnScale = nVScale;
+
+ // Calculate offsets that center the scaled screen inside the widget.
+ mnHOffset = (aWidgetSize.getWidth() - mnScale*aScreenSize.getWidth()) / 2.0;
+ mnVOffset = (aWidgetSize.getHeight() - mnScale*aScreenSize.getHeight()) / 2.0;
+ }
+ else
+ {
+ // In case of a degenerate (not yet initialized?) screen size
+ // use some meaningless default values.
+ mnScale = 1;
+ mnHOffset = 0;
+ mnVOffset = 0;
+ }
+ }
+
+
+ private XAccessibleContext mxContext;
+ private double mnScale;
+ private double mnHOffset;
+ private double mnVOffset;
+}
diff --git a/odk/examples/DevelopersGuide/Accessibility/IAccessibleObjectDisplay.java b/odk/examples/DevelopersGuide/Accessibility/IAccessibleObjectDisplay.java
new file mode 100644
index 000000000000..5e8eb3a2655c
--- /dev/null
+++ b/odk/examples/DevelopersGuide/Accessibility/IAccessibleObjectDisplay.java
@@ -0,0 +1,46 @@
+/*************************************************************************
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the BSD license.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *************************************************************************/
+
+import com.sun.star.accessibility.XAccessibleContext;
+
+interface IAccessibleObjectDisplay
+{
+
+ /** Set the accessible object to display. Call this method e.g. when a
+ new object has been focused.
+ */
+ public void setAccessibleObject (XAccessibleContext xContext);
+
+ public void updateAccessibleObject (XAccessibleContext xContext);
+}
diff --git a/odk/examples/DevelopersGuide/Accessibility/Makefile b/odk/examples/DevelopersGuide/Accessibility/Makefile
new file mode 100644
index 000000000000..6eda8233a326
--- /dev/null
+++ b/odk/examples/DevelopersGuide/Accessibility/Makefile
@@ -0,0 +1,113 @@
+#*************************************************************************
+#
+# The Contents of this file are made available subject to the terms of
+# the BSD license.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of Sun Microsystems, Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#**************************************************************************
+
+# Build the simple screen reader (SSR) described in the Developers
+# Guide Accessibility chapter.
+
+PRJ=../../..
+SETTINGS=$(PRJ)/settings
+
+include $(SETTINGS)/settings.mk
+include $(SETTINGS)/std.mk
+include $(SETTINGS)/dk.mk
+
+# Define non-platform/compiler specific settings
+EXAMPLE_NAME=DevGuideAccessibilityExample
+OUT_APP_CLASS = $(OUT_CLASS)/$(EXAMPLE_NAME)
+
+APP1_NAME =SSR
+APP1_JAR =$(OUT_APP_CLASS)/$(APP1_NAME).jar
+
+JAVAFILES = \
+ MessageArea.java \
+ ConnectionTask.java \
+ EventHandler.java \
+ EventListenerProxy.java \
+ GraphicalDisplay.java \
+ NameProvider.java \
+ IAccessibleObjectDisplay.java \
+ RegistrationThread.java \
+ SSR.java \
+ TextualDisplay.java
+
+APP1_CLASSFILES = $(patsubst %.java,$(OUT_APP_CLASS)/%.class,$(JAVAFILES))
+APP1_CLASSNAMES = $(patsubst %.java,%.class,$(JAVAFILES)) \
+ EventListenerProxy$(ICL)1.class \
+ EventListenerProxy$(ICL)2.class \
+ EventListenerProxy$(ICL)3.class \
+ EventListenerProxy$(ICL)4.class
+
+SDK_CLASSPATH = $(subst $(EMPTYSTRING) $(PATH_SEPARATOR),$(PATH_SEPARATOR),$(CLASSPATH)\
+ $(PATH_SEPARATOR)$(OUT_APP_CLASS))
+
+
+# Targets
+.PHONY: ALL
+ALL : $(EXAMPLE_NAME)
+
+include $(SETTINGS)/stdtarget.mk
+
+$(OUT_APP_CLASS)/%.class : %.java
+ -$(MKDIR) $(subst /,$(PS),$(@D))
+ $(SDK_JAVAC) $(JAVAC_FLAGS) -classpath "$(SDK_CLASSPATH)" -d $(OUT_APP_CLASS) $(JAVAFILES)
+
+$(OUT_APP_CLASS)/%.mf :
+ -$(MKDIR) $(subst /,$(PS),$(@D))
+ @echo Main-Class: com.sun.star.lib.loader.Loader> $@
+ $(ECHOLINE)>> $@
+ @echo Name: com/sun/star/lib/loader/Loader.class>> $@
+ @echo Application-Class: $*>> $@
+
+$(APP1_JAR) : $(OUT_APP_CLASS)/$(APP1_NAME).mf $(APP1_CLASSFILES)
+ -$(DEL) $(subst \\,\,$(subst /,$(PS),$@))
+ -$(MKDIR) $(subst /,$(PS),$(@D))
+ +cd $(subst /,$(PS),$(OUT_APP_CLASS)) && $(SDK_JAR) cvfm $(@F) $(basename $(@F)).mf $(APP1_CLASSNAMES)
+ +$(SDK_JAR) uvf $@ $(SDK_JAVA_UNO_BOOTSTRAP_FILES)
+
+
+$(EXAMPLE_NAME) : $(APP1_JAR)
+ @echo --------------------------------------------------------------------------------
+ @echo Before you run this example you should start your office with at least a
+ @echo new empty document and you should have enabled the accessibility support.
+ @echo Please use the following command to execute the Simple Screen Reader example!
+ @echo -
+ @echo $(MAKE) $(APP1_NAME).run
+ @echo --------------------------------------------------------------------------------
+
+%.run: $(OUT_APP_CLASS)/%.jar
+ $(SDK_JAVA) -Dcom.sun.star.lib.loader.unopath="$(OFFICE_PROGRAM_PATH)" -jar $<
+
+.PHONY: clean
+clean :
+ -$(DELRECURSIVE) $(subst /,$(PS),$(OUT_APP_CLASS))
diff --git a/odk/examples/DevelopersGuide/Accessibility/MessageArea.java b/odk/examples/DevelopersGuide/Accessibility/MessageArea.java
new file mode 100644
index 000000000000..9f3280a591a1
--- /dev/null
+++ b/odk/examples/DevelopersGuide/Accessibility/MessageArea.java
@@ -0,0 +1,133 @@
+/*************************************************************************
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the BSD license.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *************************************************************************/
+
+import java.awt.Font;
+import java.awt.Rectangle;
+import java.awt.Color;
+import java.awt.Graphics;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JScrollBar;
+
+
+
+/** A message area displays text in a scrollable text widget. It is a
+ singleton. Other objects can access it directly to display messages.
+*/
+public class MessageArea
+ extends JScrollPane
+{
+ public static synchronized MessageArea Instance ()
+ {
+ if (saInstance == null)
+ saInstance = new MessageArea ();
+ return saInstance;
+ }
+
+
+
+
+ /** Create a new message area. This method is private because the class is
+ a singleton and may therefore not be instanciated from the outside.
+ */
+ private MessageArea ()
+ {
+ maText = new JTextArea();
+ maText.setBackground (new Color (255,250,240));
+ maText.setFont (new Font ("Helvetica", Font.PLAIN, 9));
+ setViewportView (maText);
+ setVerticalScrollBarPolicy (JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+ setHorizontalScrollBarPolicy (JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+
+ printMessage (
+ "class path is " + System.getProperty ("java.class.path") + "\n");
+ }
+
+
+
+
+ /** Show the given string at the end of the message area and scroll to make
+ it visible.
+ */
+ public static synchronized void print (String aMessage)
+ {
+ Instance().printMessage(aMessage);
+ }
+
+
+
+
+ /** Show the given string at the end of the message area and scroll to make
+ it visible.
+ */
+ public static void println (String aMessage)
+ {
+ Instance().printMessage (aMessage+"\n");
+ }
+
+
+ public void paintComponent (Graphics g)
+ {
+ // Synchronize with the graphics object to prevent paint problems.
+ // Remember that this is not done by Swing itself.
+ synchronized (g)
+ {
+ JScrollBar sb = getVerticalScrollBar();
+ if (sb != null)
+ {
+ int nScrollBarValue = sb.getMaximum() - sb.getVisibleAmount() - 1;
+ sb.setValue (nScrollBarValue);
+ }
+ super.paintComponent (g);
+ }
+ }
+
+
+
+
+ /** Append the given string to the end of the text and scroll so that it
+ becomes visible. This is an internal method. Use one of the static
+ and public ones.
+ */
+ private synchronized void printMessage (String aMessage)
+ {
+ maText.append (aMessage);
+ }
+
+
+
+
+ private static MessageArea saInstance = null;
+ private JTextArea maText;
+}
diff --git a/odk/examples/DevelopersGuide/Accessibility/NameProvider.java b/odk/examples/DevelopersGuide/Accessibility/NameProvider.java
new file mode 100644
index 000000000000..9eeba18f83fd
--- /dev/null
+++ b/odk/examples/DevelopersGuide/Accessibility/NameProvider.java
@@ -0,0 +1,290 @@
+/*************************************************************************
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the BSD license.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *************************************************************************/
+
+import java.util.HashMap;
+import com.sun.star.accessibility.AccessibleStateType;
+import com.sun.star.accessibility.AccessibleEventId;
+import com.sun.star.accessibility.AccessibleRole;
+import com.sun.star.accessibility.AccessibleRelationType;
+
+
+/** Provide names for several accessibility constants groups.
+*/
+public class NameProvider
+{
+ /** Return the name of the specified state.
+ @param nStateId
+ Id of the state for which to return its name. This is one of
+ the ids listed in the <type>AccessibleStateType</const>
+ constants group.
+ @return
+ Returns the name of the specified state or an empty string if an
+ invalid / unknown state id was given.
+ */
+ public static String getStateName (int nStateId)
+ {
+ return (String)maStateMap.get (new Integer(nStateId));
+ }
+
+
+ /** Return the name of the specified event.
+ @param nEventId
+ Id of the event type for which to return its name. This is one
+ of the ids listed in the <type>AccessibleEventId</const>
+ constants group.
+ @return
+ Returns the name of the specified event type or an empty string
+ if an invalid / unknown event id was given.
+ */
+ public static String getEventName (int nEventId)
+ {
+ return (String)maEventMap.get (new Integer(nEventId));
+ }
+
+
+ /** Return the name of the specified role.
+ @param nRole
+ Id of the role for which to return its name. This is one of
+ the ids listed in the <type>AccessibleRole</const>
+ constants group.
+ @return
+ Returns the name of the specified role or an empty string if an
+ invalid / unknown role id was given.
+ */
+ public static String getRoleName (int nRole)
+ {
+ return (String)maRoleMap.get (new Integer(nRole));
+ }
+
+
+ /** Return the name of the specified relation.
+ @param nRelation
+ Id of the relation for which to return its name. This is one of
+ the ids listed in the <type>AccessibleRelationType</const>
+ constants group.
+ @return
+ Returns the name of the specified relation type or an empty
+ string if an invalid / unknown role id was given.
+ */
+ public static String getRelationName (int nRelation)
+ {
+ return (String)maRelationMap.get (new Integer(nRelation));
+ }
+
+
+ private static HashMap maStateMap = new HashMap();
+ private static HashMap maEventMap = new HashMap();
+ private static HashMap maRoleMap = new HashMap();
+ private static HashMap maRelationMap = new HashMap();
+
+ static {
+ maStateMap.put (new Integer (AccessibleStateType.INVALID), "INVALID");
+ maStateMap.put (new Integer (AccessibleStateType.ACTIVE), "ACTIVE");
+ maStateMap.put (new Integer (AccessibleStateType.ARMED), "ARMED");
+ maStateMap.put (new Integer (AccessibleStateType.BUSY), "BUSY");
+ maStateMap.put (new Integer (AccessibleStateType.CHECKED), "CHECKED");
+ maStateMap.put (new Integer (AccessibleStateType.DEFUNC), "DEFUNC");
+ maStateMap.put (new Integer (AccessibleStateType.EDITABLE), "EDITABLE");
+ maStateMap.put (new Integer (AccessibleStateType.ENABLED), "ENABLED");
+ maStateMap.put (new Integer (AccessibleStateType.EXPANDABLE), "EXPANDABLE");
+ maStateMap.put (new Integer (AccessibleStateType.EXPANDED), "EXPANDED");
+ maStateMap.put (new Integer (AccessibleStateType.FOCUSABLE), "FOCUSABLE");
+ maStateMap.put (new Integer (AccessibleStateType.FOCUSED), "FOCUSED");
+ maStateMap.put (new Integer (AccessibleStateType.HORIZONTAL), "HORIZONTAL");
+ maStateMap.put (new Integer (AccessibleStateType.ICONIFIED), "ICONIFIED");
+ maStateMap.put (new Integer (AccessibleStateType.MODAL), "MODAL");
+ maStateMap.put (new Integer (AccessibleStateType.MULTI_LINE), "MULTI_LINE");
+ maStateMap.put (new Integer (AccessibleStateType.MULTI_SELECTABLE), "MULTI_SELECTABLE");
+ maStateMap.put (new Integer (AccessibleStateType.OPAQUE), "OPAQUE");
+ maStateMap.put (new Integer (AccessibleStateType.PRESSED), "PRESSED");
+ maStateMap.put (new Integer (AccessibleStateType.RESIZABLE), "RESIZABLE");
+ maStateMap.put (new Integer (AccessibleStateType.SELECTABLE), "SELECTABLE");
+ maStateMap.put (new Integer (AccessibleStateType.SELECTED), "SELECTED");
+ maStateMap.put (new Integer (AccessibleStateType.SENSITIVE), "SENSITIVE");
+ maStateMap.put (new Integer (AccessibleStateType.SHOWING), "SHOWING");
+ maStateMap.put (new Integer (AccessibleStateType.SINGLE_LINE), "SINGLE_LINE");
+ maStateMap.put (new Integer (AccessibleStateType.STALE), "STALE");
+ maStateMap.put (new Integer (AccessibleStateType.TRANSIENT), "TRANSIENT");
+ maStateMap.put (new Integer (AccessibleStateType.VERTICAL), "VERTICAL");
+ maStateMap.put (new Integer (AccessibleStateType.VISIBLE), "VISIBLE");
+ maStateMap.put (new Integer (AccessibleStateType.MANAGES_DESCENDANTS),
+ "MANAGES_DESCENDANTS");
+ // maStateMap.put (new Integer (AccessibleStateType.INCONSISTENT),"INCONSISTENT");
+
+
+ maEventMap.put (new Integer (0),
+ "[UNKNOWN]");
+ maEventMap.put (new Integer (AccessibleEventId.NAME_CHANGED),
+ "NAME_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.DESCRIPTION_CHANGED),
+ "DESCRIPTION_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.ACTION_CHANGED),
+ "ACTION_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.STATE_CHANGED),
+ "STATE_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.ACTIVE_DESCENDANT_CHANGED),
+ "ACTIVE_DESCENDANT_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.BOUNDRECT_CHANGED),
+ "BOUNDRECT_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.CHILD),
+ "CHILD");
+ maEventMap.put (new Integer (AccessibleEventId.INVALIDATE_ALL_CHILDREN),
+ "INVALIDATE_ALL_CHILDREN");
+ maEventMap.put (new Integer (AccessibleEventId.SELECTION_CHANGED),
+ "SELECTION_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.VISIBLE_DATA_CHANGED),
+ "VISIBLE_DATA_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.VALUE_CHANGED),
+ "VALUE_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.CONTENT_FLOWS_FROM_RELATION_CHANGED),
+ "CONTENT_FLOWS_FROM_RELATION_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.CONTENT_FLOWS_TO_RELATION_CHANGED),
+ "CONTENT_FLOWS_TO_RELATION_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.CONTROLLED_BY_RELATION_CHANGED),
+ "CONTROLLED_BY_RELATION_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.CONTROLLER_FOR_RELATION_CHANGED),
+ "CONTROLLER_FOR_RELATION_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.LABEL_FOR_RELATION_CHANGED),
+ "LABEL_FOR_RELATION_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.LABELED_BY_RELATION_CHANGED),
+ "LABELED_BY_RELATION_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.MEMBER_OF_RELATION_CHANGED),
+ "MEMBER_OF_RELATION_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.SUB_WINDOW_OF_RELATION_CHANGED),
+ "SUB_WINDOW_OF_RELATION_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.CARET_CHANGED),
+ "CARET_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.TEXT_SELECTION_CHANGED),
+ "TEXT_SELECTION_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.TEXT_CHANGED),
+ "TEXT_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.TEXT_ATTRIBUTE_CHANGED),
+ "TEXT_ATTRIBUTE_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.HYPERTEXT_CHANGED),
+ "HYPERTEXT_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.TABLE_CAPTION_CHANGED),
+ "TABLE_CAPTION_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.TABLE_COLUMN_DESCRIPTION_CHANGED),
+ "TABLE_COLUMN_DESCRIPTION_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.TABLE_COLUMN_HEADER_CHANGED),
+ "TABLE_COLUMN_HEADER_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.TABLE_MODEL_CHANGED),
+ "TABLE_MODEL_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.TABLE_ROW_DESCRIPTION_CHANGED),
+ "TABLE_ROW_DESCRIPTION_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.TABLE_ROW_HEADER_CHANGED),
+ "TABLE_ROW_HEADER_CHANGED");
+ maEventMap.put (new Integer (AccessibleEventId.TABLE_SUMMARY_CHANGED),
+ "TABLE_SUMMARY_CHANGED");
+
+ maRoleMap.put (new Integer(AccessibleRole.UNKNOWN), "UNKNOWN");
+ maRoleMap.put (new Integer (AccessibleRole.UNKNOWN), "UNKNOWN");
+ maRoleMap.put (new Integer (AccessibleRole.ALERT), "ALERT");
+ maRoleMap.put (new Integer (AccessibleRole.COLUMN_HEADER), "COLUMN_HEADER");
+ maRoleMap.put (new Integer (AccessibleRole.CANVAS), "CANVAS");
+ maRoleMap.put (new Integer (AccessibleRole.CHECK_BOX), "CHECK_BOX");
+ maRoleMap.put (new Integer (AccessibleRole.CHECK_MENU_ITEM), "CHECK_MENU_ITEM");
+ maRoleMap.put (new Integer (AccessibleRole.COLOR_CHOOSER), "COLOR_CHOOSER");
+ maRoleMap.put (new Integer (AccessibleRole.COMBO_BOX), "COMBO_BOX");
+ maRoleMap.put (new Integer (AccessibleRole.DESKTOP_ICON), "DESKTOP_ICON");
+ maRoleMap.put (new Integer (AccessibleRole.DESKTOP_PANE), "DESKTOP_PANE");
+ maRoleMap.put (new Integer (AccessibleRole.DIRECTORY_PANE), "DIRECTORY_PANE");
+ maRoleMap.put (new Integer (AccessibleRole.DIALOG), "DIALOG");
+ maRoleMap.put (new Integer (AccessibleRole.DOCUMENT), "DOCUMENT");
+ maRoleMap.put (new Integer (AccessibleRole.EMBEDDED_OBJECT), "EMBEDDED_OBJECT");
+ maRoleMap.put (new Integer (AccessibleRole.END_NOTE), "END_NOTE");
+ maRoleMap.put (new Integer (AccessibleRole.FILE_CHOOSER), "FILE_CHOOSER");
+ maRoleMap.put (new Integer (AccessibleRole.FILLER), "FILLER");
+ maRoleMap.put (new Integer (AccessibleRole.FONT_CHOOSER), "FONT_CHOOSER");
+ maRoleMap.put (new Integer (AccessibleRole.FOOTER), "FOOTER");
+ maRoleMap.put (new Integer (AccessibleRole.FOOTNOTE), "FOOTNOTE");
+ maRoleMap.put (new Integer (AccessibleRole.FRAME), "FRAME");
+ maRoleMap.put (new Integer (AccessibleRole.GLASS_PANE), "GLASS_PANE");
+ maRoleMap.put (new Integer (AccessibleRole.GRAPHIC), "GRAPHIC");
+ maRoleMap.put (new Integer (AccessibleRole.GROUP_BOX), "GROUP_BOX");
+ maRoleMap.put (new Integer (AccessibleRole.HEADER), "HEADER");
+ maRoleMap.put (new Integer (AccessibleRole.HEADING), "HEADING");
+ maRoleMap.put (new Integer (AccessibleRole.HYPER_LINK), "HYPER_LINK");
+ maRoleMap.put (new Integer (AccessibleRole.ICON), "ICON");
+ maRoleMap.put (new Integer (AccessibleRole.INTERNAL_FRAME), "INTERNAL_FRAME");
+ maRoleMap.put (new Integer (AccessibleRole.LABEL), "LABEL");
+ maRoleMap.put (new Integer (AccessibleRole.LAYERED_PANE), "LAYERED_PANE");
+ maRoleMap.put (new Integer (AccessibleRole.LIST), "LIST");
+ maRoleMap.put (new Integer (AccessibleRole.LIST_ITEM), "LIST_ITEM");
+ maRoleMap.put (new Integer (AccessibleRole.MENU), "MENU");
+ maRoleMap.put (new Integer (AccessibleRole.MENU_BAR), "MENU_BAR");
+ maRoleMap.put (new Integer (AccessibleRole.MENU_ITEM), "MENU_ITEM");
+ maRoleMap.put (new Integer (AccessibleRole.OPTION_PANE), "OPTION_PANE");
+ maRoleMap.put (new Integer (AccessibleRole.PAGE_TAB), "PAGE_TAB");
+ maRoleMap.put (new Integer (AccessibleRole.PAGE_TAB_LIST), "PAGE_TAB_LIST");
+ maRoleMap.put (new Integer (AccessibleRole.PANEL), "PANEL");
+ maRoleMap.put (new Integer (AccessibleRole.PARAGRAPH), "PARAGRAPH");
+ maRoleMap.put (new Integer (AccessibleRole.PASSWORD_TEXT), "PASSWORD_TEXT");
+ maRoleMap.put (new Integer (AccessibleRole.POPUP_MENU), "POPUP_MENU");
+ maRoleMap.put (new Integer (AccessibleRole.PUSH_BUTTON), "PUSH_BUTTON");
+ maRoleMap.put (new Integer (AccessibleRole.PROGRESS_BAR), "PROGRESS_BAR");
+ maRoleMap.put (new Integer (AccessibleRole.RADIO_BUTTON), "RADIO_BUTTON");
+ maRoleMap.put (new Integer (AccessibleRole.RADIO_MENU_ITEM), "RADIO_MENU_ITEM");
+ maRoleMap.put (new Integer (AccessibleRole.ROW_HEADER), "ROW_HEADER");
+ maRoleMap.put (new Integer (AccessibleRole.ROOT_PANE), "ROOT_PANE");
+ maRoleMap.put (new Integer (AccessibleRole.SCROLL_BAR), "SCROLL_BAR");
+ maRoleMap.put (new Integer (AccessibleRole.SCROLL_PANE), "SCROLL_PANE");
+ maRoleMap.put (new Integer (AccessibleRole.SHAPE), "SHAPE");
+ maRoleMap.put (new Integer (AccessibleRole.SEPARATOR), "SEPARATOR");
+ maRoleMap.put (new Integer (AccessibleRole.SLIDER), "SLIDER");
+ maRoleMap.put (new Integer (AccessibleRole.SPIN_BOX), "SPIN_BOX");
+ maRoleMap.put (new Integer (AccessibleRole.SPLIT_PANE), "SPLIT_PANE");
+ maRoleMap.put (new Integer (AccessibleRole.STATUS_BAR), "STATUS_BAR");
+ maRoleMap.put (new Integer (AccessibleRole.TABLE), "TABLE");
+ maRoleMap.put (new Integer (AccessibleRole.TABLE_CELL), "TABLE_CELL");
+ maRoleMap.put (new Integer (AccessibleRole.TEXT), "TEXT");
+ maRoleMap.put (new Integer (AccessibleRole.TEXT_FRAME), "TEXT_FRAME");
+ maRoleMap.put (new Integer (AccessibleRole.TOGGLE_BUTTON), "TOGGLE_BUTTON");
+ maRoleMap.put (new Integer (AccessibleRole.TOOL_BAR), "TOOL_BAR");
+ maRoleMap.put (new Integer (AccessibleRole.TOOL_TIP), "TOOL_TIP");
+ maRoleMap.put (new Integer (AccessibleRole.TREE), "TREE");
+ maRoleMap.put (new Integer (AccessibleRole.VIEW_PORT), "VIEW_PORT");
+ maRoleMap.put (new Integer (AccessibleRole.WINDOW), "WINDOW");
+
+ maRelationMap.put (new Integer (AccessibleRelationType.INVALID), "INVALID");
+ maRelationMap.put (new Integer (AccessibleRelationType.CONTENT_FLOWS_FROM), "CONTENT_FLOWS_FROM");
+ maRelationMap.put (new Integer (AccessibleRelationType.CONTENT_FLOWS_TO), "CONTENT_FLOWS_TO");
+ maRelationMap.put (new Integer (AccessibleRelationType.CONTROLLED_BY), "CONTROLLED_BY");
+ maRelationMap.put (new Integer (AccessibleRelationType.CONTROLLER_FOR), "CONTROLLER_FOR");
+ maRelationMap.put (new Integer (AccessibleRelationType.LABEL_FOR), "LABEL_FOR");
+ maRelationMap.put (new Integer (AccessibleRelationType.LABELED_BY), "LABELED_BY");
+ maRelationMap.put (new Integer (AccessibleRelationType.MEMBER_OF), "MEMBER_OF");
+ maRelationMap.put (new Integer (AccessibleRelationType.SUB_WINDOW_OF), "SUB_WINDOW_OF");
+ }
+}
diff --git a/odk/examples/DevelopersGuide/Accessibility/RegistrationThread.java b/odk/examples/DevelopersGuide/Accessibility/RegistrationThread.java
new file mode 100644
index 000000000000..092941b323a7
--- /dev/null
+++ b/odk/examples/DevelopersGuide/Accessibility/RegistrationThread.java
@@ -0,0 +1,156 @@
+/*************************************************************************
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the BSD license.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *************************************************************************/
+
+import java.awt.event.ActionListener;
+import javax.swing.*;
+import java.awt.*;
+import java.util.*;
+
+import com.sun.star.awt.XTopWindowListener;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.bridge.XUnoUrlResolver;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.accessibility.*;
+import com.sun.star.awt.XExtendedToolkit;
+
+/** This class is used as a thread and registers or unregsiters a listener
+ given the constructor at all nodes of a tree of accessibility objects.
+*/
+public class RegistrationThread
+ implements Runnable
+{
+ /** Start a new thread that adds or removes the given listener at all
+ accessible objects in the sub-tree rooted in the given accessible
+ object.
+ @param aListener
+ The listener that is added or removed.
+ @param xRoot
+ The root of the sub-tree of accessibility objects.
+ @param bRegister
+ This flag decides whether to add or remove the listener.
+ */
+ public RegistrationThread (
+ EventListenerProxy aListener,
+ XAccessibleContext xRoot,
+ boolean bRegister,
+ boolean bShowMessages)
+ {
+ maListener = aListener;
+ mxRoot = xRoot;
+ mbRegister = bRegister;
+ mbShowMessages = bShowMessages;
+
+ if (mxRoot != null)
+ {
+ if (mbShowMessages)
+ MessageArea.println ("starting to register at " + mxRoot.getAccessibleName());
+ new Thread (this, "RegistrationThread").start();
+ }
+ }
+
+
+
+ public void run ()
+ {
+ System.out.println ("starting registration");
+ long nNodeCount = traverseTree (mxRoot);
+ System.out.println ("ending registration");
+ if (mbShowMessages)
+ {
+ if ( ! mbRegister)
+ MessageArea.print ("un");
+ MessageArea.println ("registered at " + nNodeCount
+ + " objects in accessibility tree of " + mxRoot.getAccessibleName());
+ }
+ }
+
+
+
+
+ /** Register this object as listener for accessibility events at all nodes
+ of the given tree.
+ @param xRoot
+ The root node of the tree at which to register.
+ */
+ public long traverseTree (XAccessibleContext xRoot)
+ {
+ long nNodeCount = 0;
+ if (xRoot != null)
+ {
+ // Register the root node.
+ XAccessibleEventBroadcaster xBroadcaster =
+ (XAccessibleEventBroadcaster) UnoRuntime.queryInterface (
+ XAccessibleEventBroadcaster.class,
+ xRoot);
+ if (xBroadcaster != null)
+ {
+ if (mbRegister)
+ xBroadcaster.addEventListener (maListener);
+ else
+ xBroadcaster.removeEventListener (maListener);
+ nNodeCount += 1;
+ }
+
+ // Call this method recursively to register all sub-trees.
+ try
+ {
+ int nChildCount = xRoot.getAccessibleChildCount();
+ for (int i=0; i<nChildCount; i++)
+ {
+ XAccessible xChild = xRoot.getAccessibleChild (i);
+ if (xChild != null)
+ nNodeCount += traverseTree (xChild.getAccessibleContext());
+ }
+ }
+ catch (com.sun.star.lang.IndexOutOfBoundsException aException)
+ {
+ // The set of children has changed since our last call to
+ // getAccesibleChildCount(). Don't try any further on this
+ // sub-tree.
+ }
+ catch (com.sun.star.lang.DisposedException aException)
+ {
+ // The child has been destroyed since our last call to
+ // getAccesibleChildCount(). That is OK. Don't try any
+ // further on this sub-tree.
+ }
+ }
+ return nNodeCount;
+ }
+
+ private EventListenerProxy maListener;
+ private XAccessibleContext mxRoot;
+ private boolean mbRegister;
+ private boolean mbShowMessages;
+}
diff --git a/odk/examples/DevelopersGuide/Accessibility/SSR.java b/odk/examples/DevelopersGuide/Accessibility/SSR.java
new file mode 100644
index 000000000000..e1830cfa2630
--- /dev/null
+++ b/odk/examples/DevelopersGuide/Accessibility/SSR.java
@@ -0,0 +1,171 @@
+/*************************************************************************
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the BSD license.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *************************************************************************/
+
+import java.awt.event.ActionListener;
+import java.awt.GridBagLayout;
+import java.awt.GridBagConstraints;
+import javax.swing.*;
+
+
+/** The simple screen reader (SSR) registers at the toolkit as focus listener
+ and displays information about the currently focused object.
+*/
+public class SSR
+ implements ActionListener
+{
+ /** Just pass the control to the SSR class.
+ */
+ public static void main (String args[])
+ {
+ new SSR ();
+ }
+
+
+
+
+ /** Create a new instance of the simple screen reader.
+ */
+ public SSR ()
+ {
+ Layout ();
+
+ // Create the event handler and tell it where to display information
+ // about the currently focused accessible object.
+ maEventHandler = new EventHandler ();
+ maEventHandler.addObjectDisplay (maTextualDisplay);
+ maEventHandler.addObjectDisplay (maGraphicalDisplay);
+ }
+
+
+
+
+ /** Setup the GUI. It is divided into three areas. The lower half is
+ ocupied by a message area that logs all the events received from
+ accessibility objects. The upper half is shared by two different
+ displays of the currently focused object. On left there is a textual
+ representation. On the right there is a graphical view of the
+ objects's outline.
+ */
+ private void Layout ()
+ {
+ GridBagConstraints constraints;
+
+ JPanel aPanel = new JPanel (true);
+ aPanel.setLayout (new GridBagLayout());
+ aPanel.setOpaque (true);
+
+ mFrame = new JFrame ("Simple Screen Reader 0.3");
+ mFrame.setContentPane(aPanel);
+ mFrame.setSize (600,400);
+
+
+ addComponent (new JLabel ("Focused Object:"),
+ 0,0, 1,1, 0,0, GridBagConstraints.WEST, GridBagConstraints.NONE);
+
+
+ maTextualDisplay = new TextualDisplay ();
+ addComponent (maTextualDisplay,
+ 0,1, 1,1, 1,1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
+
+ maGraphicalDisplay = new GraphicalDisplay ();
+ addComponent (maGraphicalDisplay,
+ 1,0, 1,2, 1,1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
+
+ addComponent (new JLabel ("Messages:"),
+ 0,2, 1,1, 0,0, GridBagConstraints.WEST, GridBagConstraints.NONE);
+
+ addComponent (MessageArea.Instance(),
+ 0,3, 2,1, 1,1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
+
+
+ JButton aButton = new JButton ("Quit SSR");
+ addComponent (aButton,
+ 0,4, 1,1, 0,0, GridBagConstraints.WEST,GridBagConstraints.NONE);
+ aButton.addActionListener (this);
+
+ mFrame.show();
+ }
+
+
+
+
+ /** Add a GUI element with the given constraints to the main window.
+ */
+ private JComponent addComponent (JComponent aComponent,
+ int x, int y, int width, int height, double weightx, double weighty,
+ int anchor, int fill)
+ {
+ aComponent.setDoubleBuffered (false);
+ GridBagConstraints aConstraints = new GridBagConstraints();
+ aConstraints.gridx = x;
+ aConstraints.gridy = y;
+ aConstraints.gridwidth = width;
+ aConstraints.gridheight = height;
+ aConstraints.weightx = weightx;
+ aConstraints.weighty = weighty;
+ aConstraints.anchor = anchor;
+ aConstraints.fill = fill;
+
+ mFrame.getContentPane().add (aComponent, aConstraints);
+
+ return aComponent;
+ }
+
+
+
+
+ /** This call-back handles button presses.
+ */
+ public void actionPerformed (java.awt.event.ActionEvent e)
+ {
+ if (e.getActionCommand().equals ("Quit SSR"))
+ {
+ maEventHandler.finalize ();
+ System.exit(0);
+ }
+ }
+
+
+ /// The main frame that contains all other GUI elements.
+ private JFrame mFrame;
+
+ /// A textutal representation of the currently focused object.
+ private TextualDisplay maTextualDisplay;
+
+ /// A graphical representation of the currently focused object.
+ private GraphicalDisplay maGraphicalDisplay;
+
+ /// The event handler that reacts to all the accessibility events.
+ private EventHandler maEventHandler;
+}
diff --git a/odk/examples/DevelopersGuide/Accessibility/TextualDisplay.java b/odk/examples/DevelopersGuide/Accessibility/TextualDisplay.java
new file mode 100644
index 000000000000..0d8ce96d978d
--- /dev/null
+++ b/odk/examples/DevelopersGuide/Accessibility/TextualDisplay.java
@@ -0,0 +1,230 @@
+/*************************************************************************
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the BSD license.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *************************************************************************/
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Dimension;
+import javax.swing.JTextArea;
+import javax.swing.JScrollPane;
+import java.util.Vector;
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleComponent;
+import com.sun.star.accessibility.XAccessibleStateSet;
+
+import com.sun.star.uno.AnyConverter;
+import com.sun.star.uno.UnoRuntime;
+
+import com.sun.star.awt.Point;
+import com.sun.star.awt.Size;
+
+/** Display textual information for a given accessible object. This
+ includes the names of that object of its ancestors as well as some
+ information retrieved from the XAccessibleContext and
+ XAccessibleComponent interfaces.
+*/
+class TextualDisplay
+ extends JScrollPane
+ implements IAccessibleObjectDisplay
+{
+ /** Create a new scroll pane that contains a text widget which display
+ information about given accessible objects.
+ */
+ public TextualDisplay ()
+ {
+ // Create a text widget for displaying the text information...
+ maText = new JTextArea (80,10);
+ maText.setBackground (new Color (250,240,230));
+ maText.setFont (new Font ("Courier", Font.PLAIN, 11));
+
+ // ...and set-up the scroll pane to show this widget.
+ setViewportView (maText);
+ setVerticalScrollBarPolicy (JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+ setHorizontalScrollBarPolicy (JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+ }
+
+
+
+
+ /** Set the accessible object to display. Call this method e.g. when a
+ new object has been focused.
+ */
+ public synchronized void setAccessibleObject (XAccessibleContext xContext)
+ {
+ // First clear the display area.
+ msTextContent = new String ();
+
+ if (xContext != null)
+ {
+ String sIndentation = showParents (xContext);
+ showContextInfo (xContext, sIndentation);
+ showComponentInfo (xContext, sIndentation);
+ }
+
+ maText.setText (msTextContent);
+ }
+
+
+
+
+ public synchronized void updateAccessibleObject (XAccessibleContext xContext)
+ {
+ setAccessibleObject (xContext);
+ }
+
+
+
+ /** Show some of the information available over the given object's
+ XAccessibleContext interface.
+ */
+ private void showContextInfo (XAccessibleContext xContext, String sIndentation)
+ {
+ // Show the description.
+ msTextContent += sIndentation + "Description: "
+ + xContext.getAccessibleDescription() + "\n";
+
+ showStates (xContext, sIndentation);
+ }
+
+
+
+
+ /** Show a list of all of the the given object's states. Use the
+ NameConverter class to transform the numerical state ids into human
+ readable names.
+ @param xContext
+ The accessible context for which to show the state names.
+ */
+ private void showStates (XAccessibleContext xContext, String sIndentation)
+ {
+ // Get the state set object...
+ XAccessibleStateSet xStateSet = xContext.getAccessibleStateSet();
+ // ...and retrieve an array of numerical ids.
+ short aStates[] = xStateSet.getStates();
+
+ // Iterate over the array and print the names of the states.
+ msTextContent += sIndentation + "States : ";
+ for (int i=0; i<aStates.length; i++)
+ {
+ if (i > 0)
+ msTextContent += ", ";
+ msTextContent += NameProvider.getStateName(aStates[i]);
+ }
+ msTextContent += "\n";
+ }
+
+
+
+
+ /** When the given object supports the XAccessibleComponent interface then
+ show its size and location on the screen.
+ */
+ private void showComponentInfo (XAccessibleContext xContext, String sIndentation)
+ {
+ // Try to cast the given accessible context to the
+ // XAccessibleComponent interface.
+ XAccessibleComponent xComponent =
+ (XAccessibleComponent)UnoRuntime.queryInterface(
+ XAccessibleComponent.class, xContext);
+ if (xComponent != null)
+ {
+ Point aLocation = xComponent.getLocationOnScreen();
+ msTextContent += sIndentation + "Position : "
+ + aLocation.X + ", " + aLocation.Y + "\n";
+
+ Size aSize = xComponent.getSize();
+ msTextContent += sIndentation + "Size : "
+ + aSize.Width + ", " + aSize.Height + "\n";
+ }
+ }
+
+
+
+
+
+ /** Print the names of the given object and its parents and return an
+ indentation string that can be used to print further information
+ about the object.
+ */
+ private String showParents (XAccessibleContext xContext)
+ {
+ // Create the path from the given object to its tree's root.
+ Vector aPathToRoot = new Vector();
+ while (xContext != null)
+ {
+ aPathToRoot.add (xContext);
+ // Go up the hierarchy one level to the object's parent.
+ try
+ {
+ XAccessible xParent = xContext.getAccessibleParent();
+ if (xParent != null)
+ xContext = xParent.getAccessibleContext();
+ else
+ xContext = null;
+ }
+ catch (Exception e)
+ {
+ System.err.println ("caught exception " + e + " while getting path to root");
+ }
+ }
+
+ // Print the path in the accessibility tree from the given context to
+ // the root.
+ String sIndentation = new String ();
+ for (int i=aPathToRoot.size()-1; i>=0; i--)
+ {
+ XAccessibleContext xParentContext = (XAccessibleContext)aPathToRoot.get(i);
+ String sParentName = xParentContext.getAccessibleName();
+ if (sParentName.length() == 0)
+ sParentName = "<unnamed> / Role "
+ + NameProvider.getRoleName(xParentContext.getAccessibleRole());
+ msTextContent += sIndentation + sParentName + "\n";
+ sIndentation += msIndentation;
+ }
+
+ return sIndentation;
+ }
+
+
+
+ /// The text widget that is used for the actual text display.
+ private JTextArea maText;
+
+ /// The indentation with which an object's child is indented.
+ private final String msIndentation = new String(" ");
+
+ /// The text content displayed by this object.
+ private String msTextContent = new String ();
+}
diff --git a/odk/examples/DevelopersGuide/Accessibility/makefile.mk b/odk/examples/DevelopersGuide/Accessibility/makefile.mk
new file mode 100644
index 000000000000..5efa8ee709ff
--- /dev/null
+++ b/odk/examples/DevelopersGuide/Accessibility/makefile.mk
@@ -0,0 +1,73 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+PRJNAME=odk
+TARGET=copying
+
+#----------------------------------------------------------------
+.INCLUDE: settings.mk
+.INCLUDE: $(PRJ)$/util$/makefile.pmk
+#----------------------------------------------------------------
+
+#----------------------------------------------------
+# this makefile is only used for copying the example
+# files into the SDK
+#----------------------------------------------------
+
+ACCESSIBILITY_FILES=\
+ $(DESTDIRDEVGUIDEEXAMPLES)$/Accessibility$/ConnectionTask.java \
+ $(DESTDIRDEVGUIDEEXAMPLES)$/Accessibility$/EventHandler.java \
+ $(DESTDIRDEVGUIDEEXAMPLES)$/Accessibility$/EventListenerProxy.java \
+ $(DESTDIRDEVGUIDEEXAMPLES)$/Accessibility$/GraphicalDisplay.java \
+ $(DESTDIRDEVGUIDEEXAMPLES)$/Accessibility$/IAccessibleObjectDisplay.java \
+ $(DESTDIRDEVGUIDEEXAMPLES)$/Accessibility$/Makefile \
+ $(DESTDIRDEVGUIDEEXAMPLES)$/Accessibility$/MessageArea.java \
+ $(DESTDIRDEVGUIDEEXAMPLES)$/Accessibility$/NameProvider.java \
+ $(DESTDIRDEVGUIDEEXAMPLES)$/Accessibility$/RegistrationThread.java \
+ $(DESTDIRDEVGUIDEEXAMPLES)$/Accessibility$/SSR.java \
+ $(DESTDIRDEVGUIDEEXAMPLES)$/Accessibility$/TextualDisplay.java
+
+DIR_FILE_LIST= \
+ $(ACCESSIBILITY_FILES)
+
+DIR_DIRECTORY_LIST=$(uniq $(DIR_FILE_LIST:d))
+DIR_CREATE_FLAG=$(MISC)$/devguide_accessibility_dirs_created.txt
+DIR_FILE_FLAG=$(MISC)$/devguide_accessibility.txt
+
+#--------------------------------------------------
+# TARGETS
+#--------------------------------------------------
+all : \
+ $(DIR_FILE_LIST) \
+ $(DIR_FILE_FLAG)
+
+#--------------------------------------------------
+# use global rules
+#--------------------------------------------------
+.INCLUDE: $(PRJ)$/util$/odk_rules.pmk
+