comparison dwt/accessibility/Accessible.d @ 42:787b5413b0ce

accessibility package
author Frank Benoit <benoit@tionex.de>
date Fri, 11 Jan 2008 05:07:22 +0100
parents
children 8cec8f536af3
comparison
equal deleted inserted replaced
41:c83c51423d03 42:787b5413b0ce
1 /*******************************************************************************
2 * Copyright (c) 2000, 2005 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 module dwt.accessibility.Accessible;
12
13 import dwt.accessibility.AccessibleListener;
14 import dwt.accessibility.AccessibleTextListener;
15 import dwt.accessibility.AccessibleControlListener;
16 import dwt.accessibility.AccessibleControlListener;
17 import dwt.accessibility.AccessibleFactory;
18 import dwt.accessibility.AccessibleObject;
19 import tango.core.Thread;
20 import dwt.SWT;
21 //import dwt.events.*;
22 import dwt.internal.gtk.OS;
23 import dwt.widgets.Control;
24 import tango.core.Array;
25 import dwt.events.DisposeListener;
26 import dwt.events.DisposeEvent;
27
28 /**
29 * Instances of this class provide a bridge between application
30 * code and assistive technology clients. Many platforms provide
31 * default accessible behavior for most widgets, and this class
32 * allows that default behavior to be overridden. Applications
33 * can get the default Accessible object for a control by sending
34 * it <code>getAccessible</code>, and then add an accessible listener
35 * to override simple items like the name and help string, or they
36 * can add an accessible control listener to override complex items.
37 * As a rule of thumb, an application would only want to use the
38 * accessible control listener to implement accessibility for a
39 * custom control.
40 *
41 * @see Control#getAccessible
42 * @see AccessibleListener
43 * @see AccessibleEvent
44 * @see AccessibleControlListener
45 * @see AccessibleControlEvent
46 *
47 * @since 2.0
48 */
49 public class Accessible {
50 AccessibleListener[] accessibleListeners;
51 AccessibleControlListener[] controlListeners;
52 AccessibleTextListener[] textListeners;
53 AccessibleObject accessibleObject;
54 Control control;
55
56 this (Control control) {
57 this.control = control;
58 AccessibleFactory.registerAccessible (this);
59 control.addDisposeListener (new class () DisposeListener {
60 public void widgetDisposed (DisposeEvent e) {
61 release ();
62 }
63 });
64 }
65
66 /**
67 * Adds the listener to the collection of listeners who will
68 * be notified when an accessible client asks for certain strings,
69 * such as name, description, help, or keyboard shortcut. The
70 * listener is notified by sending it one of the messages defined
71 * in the <code>AccessibleListener</code> interface.
72 *
73 * @param listener the listener that should be notified when the receiver
74 * is asked for a name, description, help, or keyboard shortcut string
75 *
76 * @exception IllegalArgumentException <ul>
77 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
78 * </ul>
79 * @exception SWTException <ul>
80 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
81 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
82 * </ul>
83 *
84 * @see AccessibleListener
85 * @see #removeAccessibleListener
86 */
87 public void addAccessibleListener (AccessibleListener listener) {
88 checkWidget ();
89 if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
90 accessibleListeners ~= listener;
91 }
92
93 /**
94 * Adds the listener to the collection of listeners who will
95 * be notified when an accessible client asks for custom control
96 * specific information. The listener is notified by sending it
97 * one of the messages defined in the <code>AccessibleControlListener</code>
98 * interface.
99 *
100 * @param listener the listener that should be notified when the receiver
101 * is asked for custom control specific information
102 *
103 * @exception IllegalArgumentException <ul>
104 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
105 * </ul>
106 * @exception SWTException <ul>
107 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
108 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
109 * </ul>
110 *
111 * @see AccessibleControlListener
112 * @see #removeAccessibleControlListener
113 */
114 public void addAccessibleControlListener (AccessibleControlListener listener) {
115 checkWidget ();
116 if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
117 controlListeners ~= listener;
118 }
119
120 /**
121 * Adds the listener to the collection of listeners who will
122 * be notified when an accessible client asks for custom text control
123 * specific information. The listener is notified by sending it
124 * one of the messages defined in the <code>AccessibleTextListener</code>
125 * interface.
126 *
127 * @param listener the listener that should be notified when the receiver
128 * is asked for custom text control specific information
129 *
130 * @exception IllegalArgumentException <ul>
131 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
132 * </ul>
133 * @exception SWTException <ul>
134 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
135 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
136 * </ul>
137 *
138 * @see AccessibleTextListener
139 * @see #removeAccessibleTextListener
140 *
141 * @since 3.0
142 */
143 public void addAccessibleTextListener (AccessibleTextListener listener) {
144 checkWidget ();
145 if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
146 textListeners ~= listener;
147 }
148
149 /**
150 * Returns the control for this Accessible object.
151 *
152 * @return the receiver's control
153 * @since 3.0
154 */
155 public Control getControl() {
156 return control;
157 }
158
159 /* checkWidget was copied from Widget, and rewritten to work in this package */
160 void checkWidget () {
161 if (!isValidThread ()) SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS);
162 if (control.isDisposed ()) SWT.error (SWT.ERROR_WIDGET_DISPOSED);
163 }
164
165 AccessibleListener[] getAccessibleListeners () {
166 if (accessibleListeners.length is 0 ) return null;
167 return accessibleListeners.dup;
168 }
169
170 GtkWidget* getControlHandle () {
171 return control.handle;
172 }
173
174 AccessibleControlListener[] getControlListeners () {
175 if (controlListeners.length is 0) return null;
176 return controlListeners.dup;
177 }
178
179 AccessibleTextListener[] getTextListeners () {
180 if (textListeners.length is 0) return null;
181 return textListeners.dup;
182 }
183
184 /**
185 * Invokes platform specific functionality to allocate a new accessible object.
186 * <p>
187 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
188 * API for <code>Accessible</code>. It is marked public only so that it
189 * can be shared within the packages provided by SWT. It is not
190 * available on all platforms, and should never be called from
191 * application code.
192 * </p>
193 *
194 * @param control the control to get the accessible object for
195 * @return the platform specific accessible object
196 */
197 public static Accessible internal_new_Accessible (Control control) {
198 return new Accessible (control);
199 }
200
201 /* isValidThread was copied from Widget, and rewritten to work in this package */
202 bool isValidThread () {
203 return control.getDisplay ().getThread () is Thread.getThis ();
204 }
205
206 void release () {
207 AccessibleFactory.unregisterAccessible (/*Accessible.*/this);
208 if (accessibleObject !is null) {
209 accessibleObject.release ();
210 accessibleObject = null;
211 }
212 accessibleListeners = null;
213 controlListeners = null;
214 textListeners = null;
215 }
216 /**
217 * Removes the listener from the collection of listeners who will
218 * be notified when an accessible client asks for custom control
219 * specific information.
220 *
221 * @param listener the listener that should no longer be notified when the receiver
222 * is asked for custom control specific information
223 *
224 * @exception IllegalArgumentException <ul>
225 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
226 * </ul>
227 * @exception SWTException <ul>
228 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
229 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
230 * </ul>
231 *
232 * @see AccessibleControlListener
233 * @see #addAccessibleControlListener
234 */
235 public void removeAccessibleControlListener (AccessibleControlListener listener) {
236 checkWidget ();
237 if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
238 remove( controlListeners, listener, delegate bool(AccessibleControlListener a1, AccessibleControlListener a2 ){ return a1 is a2; });
239 }
240
241 /**
242 * Removes the listener from the collection of listeners who will
243 * be notified when an accessible client asks for certain strings,
244 * such as name, description, help, or keyboard shortcut.
245 *
246 * @param listener the listener that should no longer be notified when the receiver
247 * is asked for a name, description, help, or keyboard shortcut string
248 *
249 * @exception IllegalArgumentException <ul>
250 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
251 * </ul>
252 * @exception SWTException <ul>
253 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
254 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
255 * </ul>
256 *
257 * @see AccessibleListener
258 * @see #addAccessibleListener
259 */
260 public void removeAccessibleListener (AccessibleListener listener) {
261 checkWidget ();
262 if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
263 remove( accessibleListeners, listener, delegate bool( AccessibleListener a1, AccessibleListener a2 ){ return a1 is a2; });
264 }
265
266 /**
267 * Removes the listener from the collection of listeners who will
268 * be notified when an accessible client asks for custom text control
269 * specific information.
270 *
271 * @param listener the listener that should no longer be notified when the receiver
272 * is asked for custom text control specific information
273 *
274 * @exception IllegalArgumentException <ul>
275 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
276 * </ul>
277 * @exception SWTException <ul>
278 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
279 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
280 * </ul>
281 *
282 * @see AccessibleTextListener
283 * @see #addAccessibleTextListener
284 *
285 * @since 3.0
286 */
287 public void removeAccessibleTextListener (AccessibleTextListener listener) {
288 checkWidget ();
289 if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
290 remove( textListeners, listener, delegate bool(AccessibleTextListener a1, AccessibleTextListener a2 ){ return a1 is a2; });
291 }
292
293 /**
294 * Sends a message to accessible clients that the child selection
295 * within a custom container control has changed.
296 *
297 * @exception SWTException <ul>
298 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
299 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
300 * </ul>
301 *
302 * @since 3.0
303 */
304 public void selectionChanged () {
305 checkWidget ();
306 if (accessibleObject !is null) {
307 accessibleObject.selectionChanged ();
308 }
309 }
310
311 /**
312 * Sends a message to accessible clients indicating that the focus
313 * has changed within a custom control.
314 *
315 * @param childID an identifier specifying a child of the control
316 *
317 * @exception SWTException <ul>
318 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
319 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
320 * </ul>
321 */
322 public void setFocus (int childID) {
323 checkWidget ();
324 if (accessibleObject !is null) {
325 accessibleObject.setFocus (childID);
326 }
327 }
328
329 /**
330 * Sends a message to accessible clients that the text
331 * caret has moved within a custom control.
332 *
333 * @param index the new caret index within the control
334 *
335 * @exception SWTException <ul>
336 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
337 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
338 * </ul>
339 *
340 * @since 3.0
341 */
342 public void textCaretMoved (int index) {
343 checkWidget ();
344 if (accessibleObject !is null) {
345 accessibleObject.textCaretMoved (index);
346 }
347 }
348
349 /**
350 * Sends a message to accessible clients that the text
351 * within a custom control has changed.
352 *
353 * @param type the type of change, one of <code>ACC.NOTIFY_TEXT_INSERT</code>
354 * or <code>ACC.NOTIFY_TEXT_DELETE</code>
355 * @param startIndex the text index within the control where the insertion or deletion begins
356 * @param length the non-negative length in characters of the insertion or deletion
357 *
358 * @exception SWTException <ul>
359 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
360 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
361 * </ul>
362 *
363 * @see ACC#TEXT_INSERT
364 * @see ACC#TEXT_DELETE
365 *
366 * @since 3.0
367 */
368 public void textChanged (int type, int startIndex, int length) {
369 checkWidget ();
370 if (accessibleObject !is null) {
371 accessibleObject.textChanged (type, startIndex, length);
372 }
373 }
374
375 /**
376 * Sends a message to accessible clients that the text
377 * selection has changed within a custom control.
378 *
379 * @exception SWTException <ul>
380 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
381 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
382 * </ul>
383 *
384 * @since 3.0
385 */
386 public void textSelectionChanged () {
387 checkWidget ();
388 if (accessibleObject !is null) {
389 accessibleObject.textSelectionChanged ();
390 }
391 }
392 }