25
|
1 /*******************************************************************************
|
|
2 * Copyright (c) 2000, 2007 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 * Port to the D programming language:
|
|
11 * Frank Benoit <benoit@tionex.de>
|
|
12 *******************************************************************************/
|
|
13 module org.eclipse.swt.accessibility.AccessibleObject;
|
|
14
|
|
15 import org.eclipse.swt.internal.accessibility.gtk.ATK;
|
|
16 import org.eclipse.swt.internal.gtk.OS;
|
|
17 import org.eclipse.swt.accessibility.Accessible;
|
|
18 import org.eclipse.swt.accessibility.AccessibleListener;
|
|
19 import org.eclipse.swt.accessibility.AccessibleControlListener;
|
|
20 import org.eclipse.swt.accessibility.AccessibleTextListener;
|
|
21 import org.eclipse.swt.accessibility.AccessibleEvent;
|
|
22 import org.eclipse.swt.accessibility.AccessibleControlEvent;
|
|
23 import org.eclipse.swt.accessibility.AccessibleTextEvent;
|
|
24 import org.eclipse.swt.accessibility.ACC;
|
|
25 import org.eclipse.swt.accessibility.AccessibleFactory;
|
|
26 import org.eclipse.swt.widgets.Display;
|
|
27 import java.lang.all;
|
48
|
28 version(Tango){
|
25
|
29 import tango.text.Util;
|
48
|
30 } else { // Phobos
|
|
31 }
|
25
|
32
|
|
33 class AccessibleObject {
|
|
34 AtkObject* handle;
|
|
35 int /*long*/ parentType;
|
|
36 int index = -1, id = ACC.CHILDID_SELF;
|
|
37 Accessible accessible;
|
|
38 AccessibleObject parent;
|
|
39 AccessibleObject[AtkObject*] children;
|
|
40 /*
|
|
41 * a lightweight object does not correspond to a concrete gtk widget, but
|
|
42 * to a logical child of a widget (eg.- a CTabItem, which is simply drawn)
|
|
43 */
|
|
44 bool isLightweight = false;
|
|
45
|
|
46 static String actionNamePtr;
|
|
47 static String descriptionPtr;
|
|
48 static String keybindingPtr;
|
|
49 static String namePtr;
|
|
50 static AccessibleObject[AtkObject*] AccessibleObjects;
|
|
51 static /*const*/ uint ATK_ACTION_TYPE;
|
|
52 static /*const*/ uint ATK_COMPONENT_TYPE;
|
|
53 static /*const*/ uint ATK_HYPERTEXT_TYPE;
|
|
54 static /*const*/ uint ATK_SELECTION_TYPE;
|
|
55 static /*const*/ uint ATK_TEXT_TYPE;
|
|
56 static /*const*/ bool DEBUG;
|
|
57 static bool static_this_completed = false;
|
|
58
|
|
59 package static void static_this() {
|
|
60 if( static_this_completed ) return;
|
|
61 DEBUG = Display.DEBUG;
|
|
62 ATK_ACTION_TYPE = ATK.g_type_from_name ("AtkAction");
|
|
63 ATK_COMPONENT_TYPE = ATK.g_type_from_name ("AtkComponent");
|
|
64 ATK_HYPERTEXT_TYPE = ATK.g_type_from_name ("AtkHypertext");
|
|
65 ATK_SELECTION_TYPE = ATK.g_type_from_name ("AtkSelection");
|
|
66 ATK_TEXT_TYPE = ATK.g_type_from_name ("AtkText");
|
|
67 static_this_completed = true;
|
|
68 }
|
|
69
|
|
70 this (int /*long*/ type, GtkWidget* widget, Accessible accessible, int /*long*/ parentType, bool isLightweight) {
|
|
71 handle = cast(AtkObject*)ATK.g_object_new (type, null);
|
|
72 this.parentType = parentType;
|
|
73 ATK.atk_object_initialize (handle, widget);
|
|
74 this.accessible = accessible;
|
|
75 this.isLightweight = isLightweight;
|
|
76 AccessibleObjects[handle] = this;
|
|
77 if (DEBUG) getDwtLogger().info( __FILE__, __LINE__, "new AccessibleObject: {}", handle);
|
|
78 }
|
|
79
|
|
80 void addChild (AccessibleObject child) {
|
|
81 children[child.handle] = child;
|
|
82 child.setParent (this);
|
|
83 }
|
|
84
|
|
85 package static extern(C) char* atkAction_get_keybinding (void* obj, int index) {
|
|
86 auto atkObject = cast(AtkObject*)obj;
|
|
87 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkAction_get_keybinding");
|
|
88 AccessibleObject object = getAccessibleObject (atkObject);
|
|
89 if (object is null) return null;
|
|
90 char* parentResult;
|
|
91 if (ATK.g_type_is_a (object.parentType, ATK_ACTION_TYPE)) {
|
|
92 auto superType = cast(AtkActionIface*)ATK.g_type_interface_peek_parent (ATK.ATK_ACTION_GET_IFACE (object.handle));
|
|
93 AtkActionIface* actionIface = superType;
|
|
94 if (actionIface.get_keybinding !is null) {
|
|
95 parentResult = actionIface.get_keybinding( object.handle, index );
|
|
96 }
|
|
97 }
|
|
98 AccessibleListener[] listeners = object.getAccessibleListeners ();
|
|
99 if (listeners.length is 0) return parentResult;
|
|
100
|
|
101 AccessibleEvent event = new AccessibleEvent (object);
|
|
102 event.childID = object.id;
|
|
103 if (parentResult !is null) {
|
|
104 String res = fromStringz( parentResult );
|
|
105 event.result = res.dup;
|
|
106 }
|
|
107 for (int i = 0; i < listeners.length; i++) {
|
|
108 listeners [i].getKeyboardShortcut (event);
|
|
109 }
|
|
110 if (event.result is null) return parentResult;
|
|
111 if (keybindingPtr !is null ) OS.g_free (keybindingPtr.ptr);
|
26
|
112 String name = event.result.dup ~ '\0';
|
25
|
113 char* p = cast(char*) OS.g_malloc (name.length);
|
|
114 keybindingPtr = p ? p[ 0 .. name.length ] : null;
|
|
115 return keybindingPtr.ptr;
|
|
116 }
|
|
117
|
|
118 package static extern(C) char* atkAction_get_name (void* obj, int index) {
|
|
119 auto atkObject = cast(AtkObject*)obj;
|
|
120 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkAction_get_name");
|
|
121 AccessibleObject object = getAccessibleObject (atkObject);
|
|
122 if (object is null) return null;
|
|
123 char* parentResult;
|
|
124 if (ATK.g_type_is_a (object.parentType, ATK_ACTION_TYPE)) {
|
|
125 auto actionIface = cast(AtkActionIface*)ATK.g_type_interface_peek_parent (ATK.ATK_ACTION_GET_IFACE (object.handle));
|
|
126 if (actionIface.get_name !is null) {
|
|
127 parentResult = actionIface.get_name( object.handle, index);
|
|
128 }
|
|
129 }
|
|
130 AccessibleControlListener[] listeners = object.getControlListeners ();
|
|
131 if (listeners.length is 0) return parentResult;
|
|
132
|
|
133 AccessibleControlEvent event = new AccessibleControlEvent (object);
|
|
134 event.childID = object.id;
|
|
135 if (parentResult !is null) {
|
|
136 String res = fromStringz( parentResult );
|
|
137 event.result = res.dup;
|
|
138 }
|
|
139 for (int i = 0; i < listeners.length; i++) {
|
|
140 listeners [i].getDefaultAction (event);
|
|
141 }
|
|
142 if (event.result is null) return parentResult;
|
|
143 if (actionNamePtr !is null) OS.g_free (actionNamePtr.ptr);
|
|
144
|
26
|
145 String name = event.result.dup ~ '\0';
|
25
|
146 auto p = cast(char*)OS.g_malloc (name.length);
|
|
147 actionNamePtr = p ? p[ 0 .. name.length ] : null;
|
|
148 return actionNamePtr.ptr;
|
|
149 }
|
|
150
|
|
151 package static extern(C) void atkComponent_get_extents (void* obj, int* x, int* y, int* width, int* height, int coord_type) {
|
|
152 auto atkObject = cast(AtkObject*)obj;
|
|
153 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkComponent_get_extents");
|
|
154 AccessibleObject object = getAccessibleObject (atkObject);
|
|
155 if (object is null) return 0;
|
|
156 *x = 0;
|
|
157 *y = 0;
|
|
158 *width = 0;
|
|
159 *height = 0;
|
|
160 if (ATK.g_type_is_a (object.parentType, ATK_COMPONENT_TYPE)) {
|
|
161 auto componentIface = cast(AtkComponentIface*) ATK.g_type_interface_peek_parent (ATK.ATK_COMPONENT_GET_IFACE (object.handle));
|
|
162 if (componentIface.get_extents !is null) {
|
|
163 componentIface.get_extents( object.handle, x, y, width, height, coord_type);
|
|
164 }
|
|
165 }
|
|
166 AccessibleControlListener[] listeners = object.getControlListeners ();
|
|
167 if (listeners.length is 0) return 0;
|
|
168
|
|
169 int parentX = *x, parentY = *y;
|
|
170 int parentWidth = *width, parentHeight = *height;
|
|
171 AccessibleControlEvent event = new AccessibleControlEvent (object);
|
|
172 event.childID = object.id;
|
|
173 event.x = parentX; event.y = parentY;
|
|
174 event.width = parentWidth; event.height = parentHeight;
|
|
175 if (coord_type is ATK.ATK_XY_WINDOW) {
|
|
176 /* translate control -> display, for filling in event to be dispatched */
|
|
177 auto gtkAccessible = ATK.GTK_ACCESSIBLE (object.handle);
|
|
178 auto topLevel = ATK.gtk_widget_get_toplevel (gtkAccessible.widget);
|
|
179 auto window = OS.GTK_WIDGET_WINDOW (topLevel);
|
|
180 int topWindowX, topWindowY;
|
|
181 OS.gdk_window_get_origin (window, &topWindowX, &topWindowY);
|
|
182 event.x += topWindowX;
|
|
183 event.y += topWindowY;
|
|
184 }
|
|
185 for (int i = 0; i < listeners.length; i++) {
|
|
186 listeners [i].getLocation (event);
|
|
187 }
|
|
188 if (coord_type is ATK.ATK_XY_WINDOW) {
|
|
189 /* translate display -> control, for answering to the OS */
|
|
190 auto gtkAccessible = ATK.GTK_ACCESSIBLE (object.handle);
|
|
191 auto topLevel = ATK.gtk_widget_get_toplevel (gtkAccessible.widget);
|
|
192 auto window = OS.GTK_WIDGET_WINDOW (topLevel);
|
|
193 int topWindowX, topWindowY;
|
|
194 OS.gdk_window_get_origin (window, &topWindowX, &topWindowY);
|
|
195 event.x -= topWindowX;
|
|
196 event.y -= topWindowY;
|
|
197 }
|
|
198 *x = event.x;
|
|
199 *y = event.y;
|
|
200 *width = event.width;
|
|
201 *height = event.height;
|
|
202 //return 0;
|
|
203 }
|
|
204
|
|
205 package static extern(C) void atkComponent_get_position (void* obj, int* x, int* y, int coord_type) {
|
|
206 auto atkObject = cast(AtkObject*)obj;
|
|
207 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkComponent_get_position, object: {} x:{} y:{} coord:{}", atkObject, x, y, coord_type);
|
|
208 AccessibleObject object = getAccessibleObject (atkObject);
|
|
209 if (object is null) return 0;
|
|
210 *x=0;
|
|
211 *y=0;
|
|
212 if (ATK.g_type_is_a (object.parentType, ATK_COMPONENT_TYPE)) {
|
|
213 auto componentIface = cast(AtkComponentIface*)ATK.g_type_interface_peek_parent (ATK.ATK_COMPONENT_GET_IFACE (object.handle));
|
|
214 if (componentIface.get_extents !is null) {
|
|
215 componentIface.get_position( object.handle, x, y, coord_type);
|
|
216 }
|
|
217 }
|
|
218 AccessibleControlListener[] listeners = object.getControlListeners ();
|
|
219 if (listeners.length is 0) return 0;
|
|
220
|
|
221 int parentX, parentY;
|
|
222 parentX = *x;
|
|
223 parentY = *y;
|
|
224 AccessibleControlEvent event = new AccessibleControlEvent (object);
|
|
225 event.childID = object.id;
|
|
226 event.x = parentX; event.y = parentY;
|
|
227 if (coord_type is ATK.ATK_XY_WINDOW) {
|
|
228 /* translate control -> display, for filling in event to be dispatched */
|
|
229 auto gtkAccessible = ATK.GTK_ACCESSIBLE (object.handle);
|
|
230 auto topLevel = ATK.gtk_widget_get_toplevel (gtkAccessible.widget);
|
|
231 auto window = OS.GTK_WIDGET_WINDOW (topLevel);
|
|
232 int topWindowX, topWindowY;
|
|
233 OS.gdk_window_get_origin (window, &topWindowX, &topWindowY);
|
|
234 event.x += topWindowX;
|
|
235 event.y += topWindowY;
|
|
236 }
|
|
237 for (int i = 0; i < listeners.length; i++) {
|
|
238 listeners [i].getLocation (event);
|
|
239 }
|
|
240 if (coord_type is ATK.ATK_XY_WINDOW) {
|
|
241 /* translate display -> control, for answering to the OS */
|
|
242 auto gtkAccessible = ATK.GTK_ACCESSIBLE (object.handle);
|
|
243 auto topLevel = ATK.gtk_widget_get_toplevel (gtkAccessible.widget);
|
|
244 auto window = OS.GTK_WIDGET_WINDOW (topLevel);
|
|
245 int topWindowX, topWindowY;
|
|
246 OS.gdk_window_get_origin (window, &topWindowX, &topWindowY);
|
|
247 event.x -= topWindowX;
|
|
248 event.y -= topWindowY;
|
|
249 }
|
|
250 *x=event.x;
|
|
251 *y=event.y;
|
|
252 //return 0;
|
|
253 }
|
|
254
|
|
255 //PORTING_FIXME: what about the coord_type? componentIface.get_size( object.handle, width, height, coord_type);
|
|
256 //package static extern(C) void atkComponent_get_size (void* obj, int* width, int* height, int coord_type) {
|
|
257 package static extern(C) void atkComponent_get_size (void* obj, int* width, int* height) {
|
|
258 auto atkObject = cast(AtkObject*)obj;
|
|
259 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkComponent_get_size");
|
|
260 AccessibleObject object = getAccessibleObject (atkObject);
|
|
261 if (object is null) return 0;
|
|
262 *width=0;
|
|
263 *height=0;
|
|
264 if (ATK.g_type_is_a (object.parentType, ATK_COMPONENT_TYPE)) {
|
|
265 auto componentIface = cast(AtkComponentIface*)ATK.g_type_interface_peek_parent (ATK.ATK_COMPONENT_GET_IFACE (object.handle));
|
|
266 if (componentIface.get_extents !is null) {
|
|
267 //PORTING_FIXME: what about the coord_type? componentIface.get_size( object.handle, width, height, coord_type);
|
|
268 componentIface.get_size( object.handle, width, height);
|
|
269 }
|
|
270 }
|
|
271 AccessibleControlListener[] listeners = object.getControlListeners ();
|
|
272 if (listeners.length is 0) return 0;
|
|
273
|
|
274 int parentWidth, parentHeight;
|
|
275 parentWidth= *width;
|
|
276 parentHeight= *height;
|
|
277 AccessibleControlEvent event = new AccessibleControlEvent (object);
|
|
278 event.childID = object.id;
|
|
279 event.width = parentWidth; event.height = parentHeight;
|
|
280 for (int i = 0; i < listeners.length; i++) {
|
|
281 listeners [i].getLocation (event);
|
|
282 }
|
|
283 *width=event.width;
|
|
284 *height=event.height;
|
|
285 //return 0;
|
|
286 }
|
|
287
|
|
288 package static extern(C) AtkObject* atkComponent_ref_accessible_at_point (void* obj, int x, int y, int coord_type) {
|
|
289 auto atkObject = cast(AtkObject*)obj;
|
|
290 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkComponent_ref_accessible_at_point");
|
|
291 AccessibleObject object = getAccessibleObject (atkObject);
|
|
292 if (object is null) return null;
|
|
293 AtkObject* parentResult;
|
|
294 if (ATK.g_type_is_a (object.parentType, ATK_COMPONENT_TYPE)) {
|
|
295 auto componentIface = cast(AtkComponentIface*)ATK.g_type_interface_peek_parent (ATK.ATK_COMPONENT_GET_IFACE (object.handle));
|
|
296 if (componentIface.ref_accessible_at_point !is null) {
|
|
297 parentResult = componentIface.ref_accessible_at_point( object.handle, x, y, coord_type);
|
|
298 }
|
|
299 }
|
|
300 AccessibleControlListener[] listeners = object.getControlListeners ();
|
|
301 if (listeners.length is 0) return parentResult;
|
|
302
|
|
303 AccessibleControlEvent event = new AccessibleControlEvent (object);
|
|
304 event.childID = object.id;
|
|
305 event.x = x; event.y = y;
|
|
306 if (coord_type is ATK.ATK_XY_WINDOW) {
|
|
307 /* translate control -> display, for filling in the event to be dispatched */
|
|
308 auto gtkAccessible = ATK.GTK_ACCESSIBLE (object.handle);
|
|
309 auto topLevel = ATK.gtk_widget_get_toplevel (gtkAccessible.widget);
|
|
310 auto window = OS.GTK_WIDGET_WINDOW (topLevel);
|
|
311 int topWindowX, topWindowY;
|
|
312 OS.gdk_window_get_origin (window, &topWindowX, &topWindowY);
|
|
313 event.x += topWindowX;
|
|
314 event.y += topWindowY;
|
|
315 }
|
|
316 for (int i = 0; i < listeners.length; i++) {
|
|
317 listeners [i].getChildAtPoint (event);
|
|
318 }
|
|
319 if (event.childID is object.id) event.childID = ACC.CHILDID_SELF;
|
|
320 AccessibleObject accObj = object.getChildByID (event.childID);
|
|
321 if (accObj !is null) {
|
|
322 if (parentResult !is null) OS.g_object_unref (parentResult);
|
|
323 OS.g_object_ref (accObj.handle);
|
|
324 return accObj.handle;
|
|
325 }
|
|
326 return parentResult;
|
|
327 }
|
|
328
|
|
329 package static extern(C) AtkHyperlink* atkHypertext_get_link (void* obj, int link_index) {
|
|
330 auto atkObject = cast(AtkObject*)obj;
|
|
331 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkHypertext_get_link");
|
|
332 return null;
|
|
333 }
|
|
334
|
|
335 package static extern(C) int atkHypertext_get_n_links (void* obj) {
|
|
336 auto atkObject = cast(AtkObject*)obj;
|
|
337 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkHypertext_get_n_links");
|
|
338 return 0; /* read hyperlink's name */
|
|
339 }
|
|
340
|
|
341 package static extern(C) int atkHypertext_get_link_index (void* obj, int char_index) {
|
|
342 auto atkObject = cast(AtkObject*)obj;
|
|
343 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkHypertext_get_link_index");
|
|
344 return 0;
|
|
345 }
|
|
346
|
|
347 package static extern(C) char* atkObject_get_description (AtkObject* atkObject) {
|
|
348 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkObject_get_description");
|
|
349 AccessibleObject object = getAccessibleObject (atkObject);
|
|
350 if (object is null) return null;
|
|
351 char* parentResult;
|
|
352 auto objectClass = cast(AtkObjectClass*)ATK.g_type_class_peek (object.parentType);
|
|
353 if (objectClass.get_description !is null) {
|
|
354 parentResult = objectClass.get_description(object.handle);
|
|
355 }
|
|
356 AccessibleListener[] listeners = object.getAccessibleListeners ();
|
|
357 if (listeners.length is 0) return parentResult;
|
|
358
|
|
359 AccessibleEvent event = new AccessibleEvent (object);
|
|
360 event.childID = object.id;
|
|
361 if (parentResult !is null) {
|
|
362 event.result = fromStringz( parentResult ).dup;
|
|
363 }
|
|
364 for (int i = 0; i < listeners.length; i++) {
|
|
365 listeners [i].getDescription (event);
|
|
366 }
|
|
367 if (event.result is null) return parentResult;
|
|
368 if (descriptionPtr !is null) OS.g_free (descriptionPtr.ptr);
|
|
369
|
26
|
370 String name = event.result.dup ~ '\0';
|
25
|
371 char* p = cast(char*)OS.g_malloc (name.length);
|
|
372 descriptionPtr = p ? p[ 0 .. name.length ] : null;
|
|
373 return descriptionPtr.ptr; }
|
|
374
|
|
375 package static extern(C) char* atkObject_get_name (AtkObject* atkObject) {
|
|
376 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkObject_get_name: {}", atkObject);
|
|
377 AccessibleObject object = getAccessibleObject (atkObject);
|
|
378 if (object is null) return null;
|
|
379 char* parentResult;
|
|
380 auto objectClass = cast(AtkObjectClass*)ATK.g_type_class_peek (object.parentType);
|
|
381 if (objectClass.get_name !is null) {
|
|
382 parentResult = objectClass.get_name( object.handle);
|
|
383 }
|
|
384 AccessibleListener[] listeners = object.getAccessibleListeners ();
|
|
385 if (listeners.length is 0) return parentResult;
|
|
386
|
|
387 AccessibleEvent event = new AccessibleEvent (object);
|
|
388 event.childID = object.id;
|
|
389 if (parentResult !is null) {
|
|
390 event.result = fromStringz( parentResult ).dup;
|
|
391 }
|
|
392 for (int i = 0; i < listeners.length; i++) {
|
|
393 listeners [i].getName (event);
|
|
394 }
|
|
395 if (event.result is null) return parentResult;
|
|
396 if (namePtr !is null) OS.g_free (namePtr.ptr);
|
26
|
397 String name = event.result.dup ~ '\0';
|
25
|
398 char* p = cast(char*)OS.g_malloc (name.length);
|
|
399 namePtr = p ? p[ 0 .. name.length ] : null;
|
|
400 return namePtr.ptr;
|
|
401 }
|
|
402
|
|
403 package static extern(C) int atkObject_get_n_children (AtkObject* atkObject) {
|
|
404 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkObject_get_n_children: {}", atkObject);
|
|
405 AccessibleObject object = getAccessibleObject (atkObject);
|
|
406 if (object is null) return 0;
|
|
407 int /*long*/ parentResult = 0;
|
|
408 auto objectClass = cast(AtkObjectClass*)ATK.g_type_class_peek (object.parentType);
|
|
409 if (objectClass.get_n_children !is null) {
|
|
410 parentResult = objectClass.get_n_children( object.handle);
|
|
411 }
|
|
412 AccessibleControlListener[] listeners = object.getControlListeners ();
|
|
413 if (listeners.length is 0) return parentResult;
|
|
414
|
|
415 AccessibleControlEvent event = new AccessibleControlEvent (object);
|
|
416 event.childID = object.id;
|
|
417 event.detail = cast(int)/*64*/parentResult;
|
|
418 for (int i = 0; i < listeners.length; i++) {
|
|
419 listeners [i].getChildCount (event);
|
|
420 }
|
|
421 return event.detail;
|
|
422 }
|
|
423
|
|
424 package static extern(C) int atkObject_get_index_in_parent (AtkObject* atkObject) {
|
|
425 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkObjectCB_get_index_in_parent. ");
|
|
426 AccessibleObject object = getAccessibleObject (atkObject);
|
|
427 if (object is null) return 0;
|
|
428 if (object.index !is -1) return object.index;
|
|
429 auto objectClass = cast(AtkObjectClass*)ATK.g_type_class_peek (object.parentType);
|
|
430 if (objectClass.get_index_in_parent is null) return 0;
|
|
431 return objectClass.get_index_in_parent(object. handle);
|
|
432 }
|
|
433
|
|
434 package static extern(C) AtkObject* atkObject_get_parent (AtkObject* atkObject) {
|
|
435 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkObject_get_parent: {}", atkObject);
|
|
436 AccessibleObject object = getAccessibleObject (atkObject);
|
|
437 if (object is null) return null;
|
|
438 if (object.parent !is null) return object.parent.handle;
|
|
439 auto objectClass = cast(AtkObjectClass*)ATK.g_type_class_peek (object.parentType);
|
|
440 if (objectClass.get_parent is null) return null;
|
|
441 return objectClass.get_parent( object.handle);
|
|
442 }
|
|
443
|
|
444 package static extern(C) int atkObject_get_role (AtkObject* atkObject) {
|
|
445 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkObject_get_role: {}", atkObject);
|
|
446 AccessibleObject object = getAccessibleObject (atkObject);
|
|
447 if (object is null) return 0;
|
|
448 if (object.getAccessibleListeners ().length !is 0) {
|
|
449 AccessibleControlListener[] listeners = object.getControlListeners ();
|
|
450 AccessibleControlEvent event = new AccessibleControlEvent (object);
|
|
451 event.childID = object.id;
|
|
452 event.detail = -1;
|
|
453 for (int i = 0; i < listeners.length; i++) {
|
|
454 listeners [i].getRole (event);
|
|
455 }
|
|
456 if (event.detail !is -1) {
|
|
457 switch (event.detail) {
|
|
458 /* Convert from win32 role values to atk role values */
|
|
459 case ACC.ROLE_CHECKBUTTON: return ATK.ATK_ROLE_CHECK_BOX;
|
|
460 case ACC.ROLE_CLIENT_AREA: return ATK.ATK_ROLE_DRAWING_AREA;
|
|
461 case ACC.ROLE_COMBOBOX: return ATK.ATK_ROLE_COMBO_BOX;
|
|
462 case ACC.ROLE_DIALOG: return ATK.ATK_ROLE_DIALOG;
|
|
463 case ACC.ROLE_LABEL: return ATK.ATK_ROLE_LABEL;
|
|
464 case ACC.ROLE_LINK: return ATK.ATK_ROLE_TEXT;
|
|
465 case ACC.ROLE_LIST: return ATK.ATK_ROLE_LIST;
|
|
466 case ACC.ROLE_LISTITEM: return ATK.ATK_ROLE_LIST_ITEM;
|
|
467 case ACC.ROLE_MENU: return ATK.ATK_ROLE_MENU;
|
|
468 case ACC.ROLE_MENUBAR: return ATK.ATK_ROLE_MENU_BAR;
|
|
469 case ACC.ROLE_MENUITEM: return ATK.ATK_ROLE_MENU_ITEM;
|
|
470 case ACC.ROLE_PROGRESSBAR: return ATK.ATK_ROLE_PROGRESS_BAR;
|
|
471 case ACC.ROLE_PUSHBUTTON: return ATK.ATK_ROLE_PUSH_BUTTON;
|
|
472 case ACC.ROLE_SCROLLBAR: return ATK.ATK_ROLE_SCROLL_BAR;
|
|
473 case ACC.ROLE_SEPARATOR: return ATK.ATK_ROLE_SEPARATOR;
|
|
474 case ACC.ROLE_SLIDER: return ATK.ATK_ROLE_SLIDER;
|
|
475 case ACC.ROLE_TABLE: return ATK.ATK_ROLE_LIST;
|
|
476 case ACC.ROLE_TABLECELL: return ATK.ATK_ROLE_LIST_ITEM;
|
|
477 case ACC.ROLE_TABLECOLUMNHEADER: return ATK.ATK_ROLE_TABLE_COLUMN_HEADER;
|
|
478 case ACC.ROLE_TABLEROWHEADER: return ATK.ATK_ROLE_TABLE_ROW_HEADER;
|
|
479 case ACC.ROLE_TABFOLDER: return ATK.ATK_ROLE_PAGE_TAB_LIST;
|
|
480 case ACC.ROLE_TABITEM: return ATK.ATK_ROLE_PAGE_TAB;
|
|
481 case ACC.ROLE_TEXT: return ATK.ATK_ROLE_TEXT;
|
|
482 case ACC.ROLE_TOOLBAR: return ATK.ATK_ROLE_TOOL_BAR;
|
|
483 case ACC.ROLE_TOOLTIP: return ATK.ATK_ROLE_TOOL_TIP;
|
|
484 case ACC.ROLE_TREE: return ATK.ATK_ROLE_TREE;
|
|
485 case ACC.ROLE_TREEITEM: return ATK.ATK_ROLE_LIST_ITEM;
|
|
486 case ACC.ROLE_RADIOBUTTON: return ATK.ATK_ROLE_RADIO_BUTTON;
|
|
487 case ACC.ROLE_WINDOW: return ATK.ATK_ROLE_WINDOW;
|
|
488 default:
|
|
489 }
|
|
490 }
|
|
491 }
|
|
492 auto objectClass = cast(AtkObjectClass*)ATK.g_type_class_peek (object.parentType);
|
|
493 if (objectClass.get_role is null) return 0;
|
|
494 return objectClass.get_role( object.handle);
|
|
495 }
|
|
496
|
|
497 package static extern(C) AtkObject* atkObject_ref_child (AtkObject* atkObject, int /*long*/ index) {
|
|
498 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkObject_ref_child: {} of: {}", index, atkObject);
|
|
499 AccessibleObject object = getAccessibleObject (atkObject);
|
|
500 if (object is null) return null;
|
|
501 object.updateChildren ();
|
|
502 AccessibleObject accObject = object.getChildByIndex (cast(int)/*64*/index);
|
|
503 if (accObject !is null) {
|
|
504 OS.g_object_ref (accObject.handle);
|
|
505 return accObject.handle;
|
|
506 }
|
|
507 auto objectClass = cast(AtkObjectClass*)ATK.g_type_class_peek (object.parentType);
|
|
508 if (objectClass.ref_child is null) return null;
|
|
509 return objectClass.ref_child( object.handle, index);
|
|
510 }
|
|
511
|
|
512 package static extern(C) AtkStateSet * atkObject_ref_state_set (AtkObject* atkObject) {
|
|
513 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkObject_ref_state_set");
|
|
514 AccessibleObject object = getAccessibleObject (atkObject);
|
|
515 if (object is null) return null;
|
|
516 AtkStateSet* parentResult;
|
|
517 auto objectClass = cast(AtkObjectClass*)ATK.g_type_class_peek (object.parentType);
|
|
518 if (objectClass.ref_state_set !is null) {
|
|
519 parentResult = objectClass.ref_state_set( object.handle);
|
|
520 }
|
|
521 AccessibleControlListener[] listeners = object.getControlListeners ();
|
|
522 if (listeners.length is 0) return parentResult;
|
|
523
|
|
524 auto set = parentResult;
|
|
525 AccessibleControlEvent event = new AccessibleControlEvent (object);
|
|
526 event.childID = object.id;
|
|
527 event.detail = -1;
|
|
528 for (int i = 0; i < listeners.length; i++) {
|
|
529 listeners [i].getState (event);
|
|
530 }
|
|
531 if (event.detail !is -1) {
|
|
532 /* Convert from win32 state values to atk state values */
|
|
533 int state = event.detail;
|
|
534 if ((state & ACC.STATE_BUSY) !is 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_BUSY);
|
|
535 if ((state & ACC.STATE_CHECKED) !is 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_CHECKED);
|
|
536 if ((state & ACC.STATE_EXPANDED) !is 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_EXPANDED);
|
|
537 if ((state & ACC.STATE_FOCUSABLE) !is 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_FOCUSABLE);
|
|
538 if ((state & ACC.STATE_FOCUSED) !is 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_FOCUSED);
|
|
539 if ((state & ACC.STATE_HOTTRACKED) !is 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_ARMED);
|
|
540 if ((state & ACC.STATE_INVISIBLE) is 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_VISIBLE);
|
|
541 if ((state & ACC.STATE_MULTISELECTABLE) !is 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_MULTISELECTABLE);
|
|
542 if ((state & ACC.STATE_OFFSCREEN) is 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_SHOWING);
|
|
543 if ((state & ACC.STATE_PRESSED) !is 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_PRESSED);
|
|
544 if ((state & ACC.STATE_READONLY) is 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_EDITABLE);
|
|
545 if ((state & ACC.STATE_SELECTABLE) !is 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_SELECTABLE);
|
|
546 if ((state & ACC.STATE_SELECTED) !is 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_SELECTED);
|
|
547 if ((state & ACC.STATE_SIZEABLE) !is 0) ATK.atk_state_set_add_state (set, ATK.ATK_STATE_RESIZABLE);
|
|
548 /* Note: STATE_COLLAPSED, STATE_LINKED and STATE_NORMAL have no ATK equivalents */
|
|
549 }
|
|
550 return set;
|
|
551 }
|
|
552
|
|
553 package static extern(C) int atkSelection_is_child_selected (void* obj, int index) {
|
|
554 auto atkObject = cast(AtkObject*)obj;
|
|
555 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkSelection_is_child_selected");
|
|
556 AccessibleObject object = getAccessibleObject (atkObject);
|
|
557 if (object is null) return 0;
|
|
558 int /*long*/ parentResult = 0;
|
|
559 if (ATK.g_type_is_a (object.parentType, ATK_SELECTION_TYPE)) {
|
|
560 auto selectionIface = cast(AtkSelectionIface*)ATK.g_type_interface_peek_parent (ATK.ATK_SELECTION_GET_IFACE (object.handle));
|
|
561 if (selectionIface.is_child_selected !is null) {
|
|
562 parentResult = selectionIface.is_child_selected( object.handle, index);
|
|
563 }
|
|
564 }
|
|
565 AccessibleControlListener[] listeners = object.getControlListeners ();
|
|
566 if (listeners.length is 0) return parentResult;
|
|
567
|
|
568 AccessibleControlEvent event = new AccessibleControlEvent (object);
|
|
569 event.childID = object.id;
|
|
570 for (int i = 0; i < listeners.length; i++) {
|
|
571 listeners [i].getSelection (event);
|
|
572 }
|
|
573 AccessibleObject accessibleObject = object.getChildByID (event.childID);
|
|
574 if (accessibleObject !is null) {
|
|
575 return accessibleObject.index is index ? 1 : 0;
|
|
576 }
|
|
577 return parentResult;
|
|
578 }
|
|
579
|
|
580 package static extern(C) AtkObject* atkSelection_ref_selection (void* obj, int index) {
|
|
581 auto atkObject = cast(AtkObject*)obj;
|
|
582 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkSelection_ref_selection");
|
|
583 AccessibleObject object = getAccessibleObject (atkObject);
|
|
584 if (object is null) return null;
|
|
585 AtkObject* parentResult;
|
|
586 if (ATK.g_type_is_a (object.parentType, ATK_SELECTION_TYPE)) {
|
|
587 auto selectionIface = cast(AtkSelectionIface*)ATK.g_type_interface_peek_parent (ATK.ATK_SELECTION_GET_IFACE (object.handle));
|
|
588 if (selectionIface.ref_selection !is null) {
|
|
589 parentResult = selectionIface.ref_selection( object.handle, index);
|
|
590 }
|
|
591 }
|
|
592 AccessibleControlListener[] listeners = object.getControlListeners ();
|
|
593 if (listeners.length is 0) return parentResult;
|
|
594
|
|
595 AccessibleControlEvent event = new AccessibleControlEvent (object);
|
|
596 event.childID = object.id;
|
|
597 for (int i = 0; i < listeners.length; i++) {
|
|
598 listeners [i].getSelection (event);
|
|
599 }
|
|
600 AccessibleObject accObj = object.getChildByID (event.childID);
|
|
601 if (accObj !is null) {
|
|
602 if (parentResult !is null) OS.g_object_unref (parentResult);
|
|
603 OS.g_object_ref (accObj.handle);
|
|
604 return accObj.handle;
|
|
605 }
|
|
606 return parentResult;
|
|
607 }
|
|
608
|
|
609 package static extern(C) int atkText_get_caret_offset (void* obj) {
|
|
610 auto atkObject = cast(AtkObject*)obj;
|
|
611 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkText_get_caret_offset");
|
|
612 AccessibleObject object = getAccessibleObject (atkObject);
|
|
613 if (object is null) return 0;
|
|
614 int /*long*/ parentResult = 0;
|
|
615 if (ATK.g_type_is_a (object.parentType, ATK_TEXT_TYPE)) {
|
|
616 auto textIface = cast(AtkTextIface*)ATK.g_type_interface_peek_parent (ATK.ATK_TEXT_GET_IFACE (object.handle));
|
|
617 if (textIface.get_caret_offset !is null) {
|
|
618 parentResult = textIface.get_caret_offset( object.handle);
|
|
619 }
|
|
620 }
|
|
621 AccessibleTextListener[] listeners = object.getTextListeners ();
|
|
622 if (listeners.length is 0) return parentResult;
|
|
623
|
|
624 AccessibleTextEvent event = new AccessibleTextEvent (object);
|
|
625 event.childID = object.id;
|
|
626 event.offset = cast(int)/*64*/parentResult;
|
|
627 for (int i = 0; i < listeners.length; i++) {
|
|
628 listeners [i].getCaretOffset (event);
|
|
629 }
|
|
630 return event.offset;
|
|
631 }
|
|
632
|
|
633 package static extern(C) uint atkText_get_character_at_offset (void* obj, int offset) {
|
|
634 auto atkObject = cast(AtkObject*)obj;
|
|
635 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkText_get_character_at_offset");
|
|
636 AccessibleObject object = getAccessibleObject (atkObject);
|
|
637 if (object is null) return 0;
|
|
638 String text = object.getText ();
|
|
639 if (text !is null) return text[cast(int)/*64*/offset ]; // TODO
|
|
640 if (ATK.g_type_is_a (object.parentType, ATK_TEXT_TYPE)) {
|
|
641 auto textIface = cast(AtkTextIface*)ATK.g_type_class_peek (object.parentType);
|
|
642 if (textIface.get_character_at_offset !is null) {
|
|
643 return textIface.get_character_at_offset( object.handle, offset);
|
|
644 }
|
|
645 }
|
|
646 return 0;
|
|
647 }
|
|
648
|
|
649 package static extern(C) int atkText_get_character_count (void* obj) {
|
|
650 auto atkObject = cast(AtkObject*)obj;
|
|
651 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkText_get_character_count");
|
|
652 AccessibleObject object = getAccessibleObject (atkObject);
|
|
653 if (object is null) return 0;
|
|
654 String text = object.getText ();
|
|
655 if (text !is null) return text.length;
|
|
656 if (ATK.g_type_is_a (object.parentType, ATK_TEXT_TYPE)) {
|
|
657 auto textIface = cast(AtkTextIface*)ATK.g_type_class_peek (object.parentType);
|
|
658 if (textIface.get_character_count !is null) {
|
|
659 return textIface.get_character_count( object.handle);
|
|
660 }
|
|
661 }
|
|
662 return 0;
|
|
663 }
|
|
664
|
|
665 package static extern(C) int atkText_get_n_selections (void* obj) {
|
|
666 auto atkObject = cast(AtkObject*)obj;
|
|
667 if (DEBUG) getDwtLogger().info( __FILE__, __LINE__, "-->atkText_get_n_selections");
|
|
668 AccessibleObject object = getAccessibleObject (atkObject);
|
|
669 if (object is null) return 0;
|
|
670 int /*long*/ parentResult = 0;
|
|
671 if (ATK.g_type_is_a (object.parentType, ATK_TEXT_TYPE)) {
|
|
672 auto textIface = cast(AtkTextIface*)ATK.g_type_interface_peek_parent (ATK.ATK_TEXT_GET_IFACE (object.handle));
|
|
673 if (textIface.get_n_selections !is null) {
|
|
674 parentResult = textIface.get_n_selections( object.handle);
|
|
675 }
|
|
676 }
|
|
677 AccessibleTextListener[] listeners = object.getTextListeners ();
|
|
678 if (listeners.length is 0) return parentResult;
|
|
679
|
|
680 AccessibleTextEvent event = new AccessibleTextEvent (object);
|
|
681 event.childID = object.id;
|
|
682 for (int i = 0; i < listeners.length; i++) {
|
|
683 listeners [i].getSelectionRange (event);
|
|
684 }
|
|
685 return event.length is 0 ? parentResult : 1;
|
|
686 }
|
|
687
|
|
688 package static extern(C) char* atkText_get_selection (void* obj, int selection_num, int* start_offset, int* end_offset) {
|
|
689 auto atkObject = cast(AtkObject*)obj;
|
|
690 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkText_get_selection");
|
|
691 AccessibleObject object = getAccessibleObject (atkObject);
|
|
692 if (object is null) return null;
|
|
693 *start_offset=0;
|
|
694 *end_offset=0;
|
|
695 if (ATK.g_type_is_a (object.parentType, ATK_TEXT_TYPE)) {
|
|
696 auto textIface = cast(AtkTextIface*)ATK.g_type_interface_peek_parent (ATK.ATK_TEXT_GET_IFACE (object.handle));
|
|
697 if (textIface.get_selection !is null) {
|
|
698 textIface.get_selection( object.handle, selection_num, start_offset, end_offset );
|
|
699 }
|
|
700 }
|
|
701 AccessibleTextListener[] listeners = object.getTextListeners ();
|
|
702 if (listeners.length is 0) return null;
|
|
703
|
|
704 AccessibleTextEvent event = new AccessibleTextEvent (object);
|
|
705 event.childID = object.id;
|
|
706 int parentStart;
|
|
707 int parentEnd;
|
|
708 parentStart= *start_offset;
|
|
709 parentEnd= *end_offset;
|
|
710 event.offset = parentStart;
|
|
711 event.length = parentEnd - parentStart;
|
|
712 for (int i = 0; i < listeners.length; i++) {
|
|
713 listeners [i].getSelectionRange (event);
|
|
714 }
|
|
715 *start_offset = event.offset;
|
|
716 *end_offset = event.offset + event.length;
|
|
717 return null;
|
|
718 }
|
|
719
|
|
720 package static extern(C) char* atkText_get_text (void* obj, int start_offset, int end_offset) {
|
|
721 auto atkObject = cast(AtkObject*)obj;
|
|
722 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkText_get_text: {},{}", start_offset, end_offset);
|
|
723 AccessibleObject object = getAccessibleObject (atkObject);
|
|
724 if (object is null) return null;
|
|
725 String text = object.getText ();
|
|
726 if (text.length > 0) {
|
|
727 if (end_offset is -1) {
|
|
728 end_offset = text.length ;
|
|
729 } else {
|
|
730 end_offset = Math.min (end_offset, text.length );
|
|
731 }
|
|
732 start_offset = Math.min (start_offset, end_offset);
|
|
733 text = text[ start_offset .. end_offset ];
|
|
734 auto result = cast(char*)OS.g_malloc (text.length+1);
|
|
735 result[ 0 .. text.length ] = text;
|
|
736 result[ text.length ] = '\0';
|
|
737 return result;
|
|
738 }
|
|
739 return null;
|
|
740 }
|
|
741
|
|
742 package static extern(C) char* atkText_get_text_after_offset (void* obj, int offset_value, int boundary_type, int* start_offset, int* end_offset) {
|
|
743 auto atkObject = cast(AtkObject*)obj;
|
|
744 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkText_get_text_after_offset");
|
|
745 AccessibleObject object = getAccessibleObject (atkObject);
|
|
746 if (object is null) return null;
|
|
747 int offset = cast(int)/*64*/offset_value;
|
|
748 String text = object.getText ();
|
|
749 if (text.length > 0) {
|
|
750 int length = text.length ;
|
|
751 offset = Math.min (offset, length - 1);
|
|
752 int startBounds = offset;
|
|
753 int endBounds = offset;
|
|
754 switch (cast(int)/*64*/boundary_type) {
|
|
755 case ATK.ATK_TEXT_BOUNDARY_CHAR: {
|
|
756 if (length > offset) endBounds++;
|
|
757 break;
|
|
758 }
|
|
759 case ATK.ATK_TEXT_BOUNDARY_WORD_START: {
|
|
760 int wordStart1 = nextIndexOfChar (text, " !?.\n", offset - 1);
|
|
761 if (wordStart1 is -1) {
|
|
762 startBounds = endBounds = length;
|
|
763 break;
|
|
764 }
|
|
765 wordStart1 = nextIndexOfNotChar (text, " !?.\n", wordStart1);
|
|
766 if (wordStart1 is length) {
|
|
767 startBounds = endBounds = length;
|
|
768 break;
|
|
769 }
|
|
770 startBounds = wordStart1;
|
|
771 int wordStart2 = nextIndexOfChar (text, " !?.\n", wordStart1);
|
|
772 if (wordStart2 is -1) {
|
|
773 endBounds = length;
|
|
774 break;
|
|
775 }
|
|
776 endBounds = nextIndexOfNotChar (text, " !?.\n", wordStart2);
|
|
777 break;
|
|
778 }
|
|
779 case ATK.ATK_TEXT_BOUNDARY_WORD_END: {
|
|
780 int previousWordEnd = previousIndexOfNotChar (text, " \n", offset);
|
|
781 if (previousWordEnd is -1 || previousWordEnd !is offset - 1) {
|
|
782 offset = nextIndexOfNotChar (text, " \n", offset);
|
|
783 }
|
|
784 if (offset is -1) {
|
|
785 startBounds = endBounds = length;
|
|
786 break;
|
|
787 }
|
|
788 int wordEnd1 = nextIndexOfChar (text, " !?.\n", cast(int)/*64*/offset);
|
|
789 if (wordEnd1 is -1) {
|
|
790 startBounds = endBounds = length;
|
|
791 break;
|
|
792 }
|
|
793 wordEnd1 = nextIndexOfNotChar (text, "!?.", wordEnd1);
|
|
794 if (wordEnd1 is length) {
|
|
795 startBounds = endBounds = length;
|
|
796 break;
|
|
797 }
|
|
798 startBounds = wordEnd1;
|
|
799 int wordEnd2 = nextIndexOfNotChar (text, " \n", wordEnd1);
|
|
800 if (wordEnd2 is length) {
|
|
801 startBounds = endBounds = length;
|
|
802 break;
|
|
803 }
|
|
804 wordEnd2 = nextIndexOfChar (text, " !?.\n", wordEnd2);
|
|
805 if (wordEnd2 is -1) {
|
|
806 endBounds = length;
|
|
807 break;
|
|
808 }
|
|
809 endBounds = nextIndexOfNotChar (text, "!?.", wordEnd2);
|
|
810 break;
|
|
811 }
|
|
812 case ATK.ATK_TEXT_BOUNDARY_SENTENCE_START: {
|
|
813 int previousSentenceEnd = previousIndexOfChar (text, "!?.", offset);
|
|
814 int previousText = previousIndexOfNotChar (text, " !?.\n", offset);
|
|
815 int sentenceStart1 = 0;
|
|
816 if (previousSentenceEnd >= previousText) {
|
|
817 sentenceStart1 = nextIndexOfNotChar (text, " !?.\n", offset);
|
|
818 } else {
|
|
819 sentenceStart1 = nextIndexOfChar (text, "!?.", offset);
|
|
820 if (sentenceStart1 is -1) {
|
|
821 startBounds = endBounds = length;
|
|
822 break;
|
|
823 }
|
|
824 sentenceStart1 = nextIndexOfNotChar (text, " !?.\n", sentenceStart1);
|
|
825 }
|
|
826 if (sentenceStart1 is length) {
|
|
827 startBounds = endBounds = length;
|
|
828 break;
|
|
829 }
|
|
830 startBounds = sentenceStart1;
|
|
831 int sentenceStart2 = nextIndexOfChar (text, "!?.", sentenceStart1);
|
|
832 if (sentenceStart2 is -1) {
|
|
833 endBounds = length;
|
|
834 break;
|
|
835 }
|
|
836 endBounds = nextIndexOfNotChar (text, " !?.\n", sentenceStart2);
|
|
837 break;
|
|
838 }
|
|
839 case ATK.ATK_TEXT_BOUNDARY_SENTENCE_END: {
|
|
840 int sentenceEnd1 = nextIndexOfChar (text, "!?.", offset);
|
|
841 if (sentenceEnd1 is -1) {
|
|
842 startBounds = endBounds = length;
|
|
843 break;
|
|
844 }
|
|
845 sentenceEnd1 = nextIndexOfNotChar (text, "!?.", sentenceEnd1);
|
|
846 if (sentenceEnd1 is length) {
|
|
847 startBounds = endBounds = length;
|
|
848 break;
|
|
849 }
|
|
850 startBounds = sentenceEnd1;
|
|
851 int sentenceEnd2 = nextIndexOfNotChar (text, " \n", sentenceEnd1);
|
|
852 if (sentenceEnd2 is length) {
|
|
853 startBounds = endBounds = length;
|
|
854 break;
|
|
855 }
|
|
856 sentenceEnd2 = nextIndexOfChar (text, "!?.", sentenceEnd2);
|
|
857 if (sentenceEnd2 is -1) {
|
|
858 endBounds = length;
|
|
859 break;
|
|
860 }
|
|
861 endBounds = nextIndexOfNotChar (text, "!?.", sentenceEnd2);
|
|
862 break;
|
|
863 }
|
|
864 case ATK.ATK_TEXT_BOUNDARY_LINE_START: {
|
|
865 int lineStart1 = locate( text, '\n' );
|
|
866 if( lineStart1 is text.length ) lineStart1 = -1;
|
|
867 if (lineStart1 is -1) {
|
|
868 startBounds = endBounds = length;
|
|
869 break;
|
|
870 }
|
|
871 lineStart1 = nextIndexOfNotChar (text, "\n", lineStart1);
|
|
872 if (lineStart1 is length) {
|
|
873 startBounds = endBounds = length;
|
|
874 break;
|
|
875 }
|
|
876 startBounds = lineStart1;
|
|
877 int lineStart2 = locate( text, '\n' );
|
|
878 if( lineStart2 is text.length ) lineStart2 = -1;
|
|
879 if (lineStart2 is -1) {
|
|
880 endBounds = length;
|
|
881 break;
|
|
882 }
|
|
883 lineStart2 = nextIndexOfNotChar (text, "\n", lineStart2);
|
|
884 endBounds = lineStart2;
|
|
885 break;
|
|
886 }
|
|
887 case ATK.ATK_TEXT_BOUNDARY_LINE_END: {
|
|
888 int lineEnd1 = nextIndexOfChar (text, "\n", offset);
|
|
889 if (lineEnd1 is -1) {
|
|
890 startBounds = endBounds = length;
|
|
891 break;
|
|
892 }
|
|
893 startBounds = lineEnd1;
|
|
894 if (startBounds is length) {
|
|
895 endBounds = length;
|
|
896 break;
|
|
897 }
|
|
898 int lineEnd2 = nextIndexOfChar (text, "\n", lineEnd1 + 1);
|
|
899 if (lineEnd2 is -1) {
|
|
900 endBounds = length;
|
|
901 break;
|
|
902 }
|
|
903 endBounds = lineEnd2;
|
|
904 break;
|
|
905 }
|
|
906 default:
|
|
907 }
|
|
908 *start_offset=startBounds;
|
|
909 *end_offset=endBounds;
|
|
910 text = text[startBounds .. endBounds ];
|
|
911 auto result = cast(char*)OS.g_malloc (text.length+1);
|
|
912 result[ 0 .. text.length ] = text;
|
|
913 result[ text.length ] = '\0';
|
|
914 return result;
|
|
915 }
|
|
916 return null;
|
|
917 }
|
|
918
|
|
919 package static extern(C) char* atkText_get_text_at_offset (void* obj, int offset_value, int boundary_type, int* start_offset, int* end_offset) {
|
|
920 auto atkObject = cast(AtkObject*)obj;
|
|
921 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkText_get_text_at_offset: {} start: {} end: {}", offset_value, start_offset, end_offset);
|
|
922 AccessibleObject object = getAccessibleObject (atkObject);
|
|
923 if (object is null) return null;
|
|
924 int offset = offset_value;
|
|
925 String text = object.getText ();
|
|
926 if (text.length > 0) {
|
|
927 int length = text.length;
|
|
928 offset = Math.min (offset, length - 1);
|
|
929 int startBounds = offset;
|
|
930 int endBounds = offset;
|
|
931 switch (boundary_type) {
|
|
932 case ATK.ATK_TEXT_BOUNDARY_CHAR: {
|
|
933 if (length > offset) endBounds++;
|
|
934 break;
|
|
935 }
|
|
936 case ATK.ATK_TEXT_BOUNDARY_WORD_START: {
|
|
937 int wordStart1 = previousIndexOfNotChar (text, " !?.\n", offset);
|
|
938 if (wordStart1 is -1) {
|
|
939 startBounds = endBounds = 0;
|
|
940 break;
|
|
941 }
|
|
942 wordStart1 = previousIndexOfChar (text, " !?.\n", wordStart1) + 1;
|
|
943 if (wordStart1 is -1) {
|
|
944 startBounds = 0;
|
|
945 break;
|
|
946 }
|
|
947 startBounds = wordStart1;
|
|
948 int wordStart2 = nextIndexOfChar (text, " !?.\n", wordStart1);
|
|
949 endBounds = nextIndexOfNotChar (text, " !?.\n", wordStart2);
|
|
950 break;
|
|
951 }
|
|
952 case ATK.ATK_TEXT_BOUNDARY_WORD_END: {
|
|
953 int wordEnd1 = previousIndexOfNotChar (text, "!?.", offset + 1);
|
|
954 wordEnd1 = previousIndexOfChar (text, " !?.\n", wordEnd1);
|
|
955 wordEnd1 = previousIndexOfNotChar (text, " \n", wordEnd1 + 1);
|
|
956 if (wordEnd1 is -1) {
|
|
957 startBounds = endBounds = 0;
|
|
958 break;
|
|
959 }
|
|
960 startBounds = wordEnd1 + 1;
|
|
961 int wordEnd2 = nextIndexOfNotChar (text, " \n", startBounds);
|
|
962 if (wordEnd2 is length) {
|
|
963 endBounds = startBounds;
|
|
964 break;
|
|
965 }
|
|
966 wordEnd2 = nextIndexOfChar (text, " !?.\n", wordEnd2);
|
|
967 if (wordEnd2 is -1) {
|
|
968 endBounds = startBounds;
|
|
969 break;
|
|
970 }
|
|
971 endBounds = nextIndexOfNotChar (text, "!?.", wordEnd2);
|
|
972 break;
|
|
973 }
|
|
974 case ATK.ATK_TEXT_BOUNDARY_SENTENCE_START: {
|
|
975 int sentenceStart1 = previousIndexOfNotChar (text, " !?.\n", offset + 1);
|
|
976 if (sentenceStart1 is -1) {
|
|
977 startBounds = endBounds = 0;
|
|
978 break;
|
|
979 }
|
|
980 sentenceStart1 = previousIndexOfChar (text, "!?.", sentenceStart1) + 1;
|
|
981 startBounds = nextIndexOfNotChar (text, " \n", sentenceStart1);
|
|
982 int sentenceStart2 = nextIndexOfChar (text, "!?.", startBounds);
|
|
983 endBounds = nextIndexOfNotChar (text, " !?.\n", sentenceStart2);
|
|
984 break;
|
|
985 }
|
|
986 case ATK.ATK_TEXT_BOUNDARY_SENTENCE_END: {
|
|
987 int sentenceEnd1 = previousIndexOfNotChar (text, "!?.", offset + 1);
|
|
988 sentenceEnd1 = previousIndexOfChar (text, "!?.", sentenceEnd1);
|
|
989 sentenceEnd1 = previousIndexOfNotChar (text, " \n", sentenceEnd1 + 1);
|
|
990 if (sentenceEnd1 is -1) {
|
|
991 startBounds = endBounds = 0;
|
|
992 break;
|
|
993 }
|
|
994 startBounds = sentenceEnd1 + 1;
|
|
995 int sentenceEnd2 = nextIndexOfNotChar (text, " \n", startBounds);
|
|
996 if (sentenceEnd2 is length) {
|
|
997 endBounds = startBounds;
|
|
998 break;
|
|
999 }
|
|
1000 sentenceEnd2 = nextIndexOfChar (text, "!?.", sentenceEnd2);
|
|
1001 if (sentenceEnd2 is -1) {
|
|
1002 endBounds = startBounds;
|
|
1003 break;
|
|
1004 }
|
|
1005 endBounds = nextIndexOfNotChar (text, "!?.", sentenceEnd2);
|
|
1006 break;
|
|
1007 }
|
|
1008 case ATK.ATK_TEXT_BOUNDARY_LINE_START: {
|
|
1009 startBounds = previousIndexOfChar (text, "\n", offset) + 1;
|
|
1010 int lineEnd2 = nextIndexOfChar (text, "\n", startBounds);
|
|
1011 if (lineEnd2 < length) lineEnd2++;
|
|
1012 endBounds = lineEnd2;
|
|
1013 break;
|
|
1014 }
|
|
1015 case ATK.ATK_TEXT_BOUNDARY_LINE_END: {
|
|
1016 int lineEnd1 = previousIndexOfChar (text, "\n", offset);
|
|
1017 if (lineEnd1 is -1) {
|
|
1018 startBounds = endBounds = 0;
|
|
1019 break;
|
|
1020 }
|
|
1021 startBounds = lineEnd1;
|
|
1022 endBounds = nextIndexOfChar (text, "\n", lineEnd1 + 1);
|
|
1023 }
|
|
1024 default:
|
|
1025 }
|
|
1026 *start_offset=startBounds;
|
|
1027 *end_offset=endBounds;
|
|
1028 text = text[startBounds .. endBounds];
|
|
1029 auto result = cast(char*) OS.g_malloc (text.length+1);
|
|
1030 result[ 0 .. text.length ] = text;
|
|
1031 result[ text.length ] = '\0';
|
|
1032 return result;
|
|
1033 }
|
|
1034 return null;
|
|
1035 }
|
|
1036
|
|
1037 package static extern(C) char* atkText_get_text_before_offset (void* obj, int offset_value, int boundary_type, int* start_offset, int* end_offset) {
|
|
1038 auto atkObject = cast(AtkObject*)obj;
|
|
1039 if (DEBUG) getDwtLogger().info (__FILE__, __LINE__, "-->atkText_get_text_before_offset");
|
|
1040 AccessibleObject object = getAccessibleObject (atkObject);
|
|
1041 if (object is null) return null;
|
|
1042 int offset = offset_value;
|
|
1043 String text = object.getText ();
|
|
1044 if (text.length > 0) {
|
|
1045 int length = text.length;
|
|
1046 offset = Math.min (offset, length - 1);
|
|
1047 int startBounds = offset;
|
|
1048 int endBounds = offset;
|
|
1049 switch (boundary_type) {
|
|
1050 case ATK.ATK_TEXT_BOUNDARY_CHAR: {
|
|
1051 if (length >= offset && offset > 0) startBounds--;
|
|
1052 break;
|
|
1053 }
|
|
1054 case ATK.ATK_TEXT_BOUNDARY_WORD_START: {
|
|
1055 int wordStart1 = previousIndexOfChar (text, " !?.\n", offset - 1);
|
|
1056 if (wordStart1 is -1) {
|
|
1057 startBounds = endBounds = 0;
|
|
1058 break;
|
|
1059 }
|
|
1060 int wordStart2 = previousIndexOfNotChar (text, " !?.\n", wordStart1);
|
|
1061 if (wordStart2 is -1) {
|
|
1062 startBounds = endBounds = 0;
|
|
1063 break;
|
|
1064 }
|
|
1065 endBounds = wordStart1 + 1;
|
|
1066 startBounds = previousIndexOfChar (text, " !?.\n", wordStart2) + 1;
|
|
1067 break;
|
|
1068 }
|
|
1069 case ATK.ATK_TEXT_BOUNDARY_WORD_END: {
|
|
1070 int wordEnd1 =previousIndexOfChar (text, " !?.\n", offset);
|
|
1071 if (wordEnd1 is -1) {
|
|
1072 startBounds = endBounds = 0;
|
|
1073 break;
|
|
1074 }
|
|
1075 wordEnd1 = previousIndexOfNotChar (text, " \n", wordEnd1 + 1);
|
|
1076 if (wordEnd1 is -1) {
|
|
1077 startBounds = endBounds = 0;
|
|
1078 break;
|
|
1079 }
|
|
1080 endBounds = wordEnd1 + 1;
|
|
1081 int wordEnd2 = previousIndexOfNotChar (text, " !?.\n", endBounds);
|
|
1082 wordEnd2 = previousIndexOfChar (text, " !?.\n", wordEnd2);
|
|
1083 if (wordEnd2 is -1) {
|
|
1084 startBounds = 0;
|
|
1085 break;
|
|
1086 }
|
|
1087 startBounds = previousIndexOfNotChar (text, " \n", wordEnd2 + 1) + 1;
|
|
1088 break;
|
|
1089 }
|
|
1090 case ATK.ATK_TEXT_BOUNDARY_SENTENCE_START: {
|
|
1091 int sentenceStart1 = previousIndexOfChar (text, "!?.", offset);
|
|
1092 if (sentenceStart1 is -1) {
|
|
1093 startBounds = endBounds = 0;
|
|
1094 break;
|
|
1095 }
|
|
1096 int sentenceStart2 = previousIndexOfNotChar (text, "!?.", sentenceStart1);
|
|
1097 if (sentenceStart2 is -1) {
|
|
1098 startBounds = endBounds = 0;
|
|
1099 break;
|
|
1100 }
|
|
1101 endBounds = sentenceStart1 + 1;
|
|
1102 startBounds = previousIndexOfChar (text, "!?.", sentenceStart2) + 1;
|
|
1103 break;
|
|
1104 }
|
|
1105 case ATK.ATK_TEXT_BOUNDARY_SENTENCE_END: {
|
|
1106 int sentenceEnd1 = previousIndexOfChar (text, "!?.", offset);
|
|
1107 if (sentenceEnd1 is -1) {
|
|
1108 startBounds = endBounds = 0;
|
|
1109 break;
|
|
1110 }
|
|
1111 sentenceEnd1 = previousIndexOfNotChar (text, " \n", sentenceEnd1 + 1);
|
|
1112 if (sentenceEnd1 is -1) {
|
|
1113 startBounds = endBounds = 0;
|
|
1114 break;
|
|
1115 }
|
|
1116 endBounds = sentenceEnd1 + 1;
|
|
1117 int sentenceEnd2 = previousIndexOfNotChar (text, "!?.", endBounds);
|
|
1118 sentenceEnd2 = previousIndexOfChar (text, "!?.", sentenceEnd2);
|
|
1119 if (sentenceEnd2 is -1) {
|
|
1120 startBounds = 0;
|
|
1121 break;
|
|
1122 }
|
|
1123 startBounds = previousIndexOfNotChar (text, " \n", sentenceEnd2 + 1) + 1;
|
|
1124 break;
|
|
1125 }
|
|
1126 case ATK.ATK_TEXT_BOUNDARY_LINE_START: {
|
|
1127 int lineStart1 = previousIndexOfChar (text, "\n", offset);
|
|
1128 if (lineStart1 is -1) {
|
|
1129 startBounds = endBounds = 0;
|
|
1130 break;
|
|
1131 }
|
|
1132 endBounds = lineStart1 + 1;
|
|
1133 startBounds = previousIndexOfChar (text, "\n", lineStart1) + 1;
|
|
1134 break;
|
|
1135 }
|
|
1136 case ATK.ATK_TEXT_BOUNDARY_LINE_END: {
|
|
1137 int lineEnd1 = previousIndexOfChar (text, "\n", offset);
|
|
1138 if (lineEnd1 is -1) {
|
|
1139 startBounds = endBounds = 0;
|
|
1140 break;
|
|
1141 }
|
|
1142 endBounds = lineEnd1;
|
|
1143 startBounds = previousIndexOfChar (text, "\n", lineEnd1);
|
|
1144 if (startBounds is -1) startBounds = 0;
|
|
1145 break;
|
|
1146 }
|
|
1147 default:
|
|
1148 }
|
|
1149 *start_offset=startBounds;
|
|
1150 *end_offset=endBounds;
|
|
1151 text = text[startBounds .. endBounds];
|
|
1152 auto result = cast(char*)OS.g_malloc (text.length+1);
|
|
1153 result[ 0 .. text.length ] = text;
|
|
1154 result[ text.length ] = '\0';
|
|
1155 return result;
|
|
1156 }
|
|
1157 return null;
|
|
1158 }
|
|
1159
|
|
1160 AccessibleListener[] getAccessibleListeners () {
|
|
1161 if (accessible is null) return new AccessibleListener [0];
|
|
1162 AccessibleListener[] result = accessible.getAccessibleListeners ();
|
|
1163 return result !is null ? result : new AccessibleListener [0];
|
|
1164 }
|
|
1165
|
|
1166 static AccessibleObject getAccessibleObject (AtkObject* atkObject) {
|
|
1167 return AccessibleObjects[atkObject];
|
|
1168 }
|
|
1169
|
|
1170 AccessibleObject getChildByHandle (AtkObject* handle) {
|
|
1171 return children[handle];
|
|
1172 }
|
|
1173
|
|
1174 AccessibleObject getChildByID (int childId) {
|
|
1175 if (childId is ACC.CHILDID_SELF) return this;
|
|
1176 foreach( object; children ){
|
|
1177 if (object.id is childId) return object;
|
|
1178 }
|
|
1179 return null;
|
|
1180 }
|
|
1181
|
|
1182 AccessibleObject getChildByIndex (int childIndex) {
|
|
1183 foreach( object; children ){
|
|
1184 if (object.index is childIndex) return object;
|
|
1185 }
|
|
1186 return null;
|
|
1187 }
|
|
1188
|
|
1189 AccessibleControlListener[] getControlListeners () {
|
|
1190 if (accessible is null) return new AccessibleControlListener [0];
|
|
1191 AccessibleControlListener[] result = accessible.getControlListeners ();
|
|
1192 return result !is null ? result : new AccessibleControlListener [0];
|
|
1193 }
|
|
1194
|
|
1195 String getText () {
|
|
1196 char* parentResult;
|
|
1197 String parentText = ""; //$NON-NLS-1$
|
|
1198 if (ATK.g_type_is_a (parentType, ATK_TEXT_TYPE)) {
|
|
1199 auto textIface = cast(AtkTextIface*)ATK.g_type_interface_peek_parent (ATK.ATK_TEXT_GET_IFACE (handle));
|
|
1200 int /*long*/ characterCount = 0;
|
|
1201 if (textIface.get_character_count !is null) {
|
|
1202 characterCount = textIface.get_character_count( handle);
|
|
1203 }
|
|
1204 if (characterCount > 0 && textIface.get_text !is null) {
|
|
1205 parentResult = textIface.get_text( handle, 0, characterCount);
|
|
1206 if (parentResult !is null) {
|
|
1207 parentText = fromStringz( parentResult ).dup;
|
|
1208 }
|
|
1209 }
|
|
1210 }
|
|
1211 AccessibleControlListener[] controlListeners = getControlListeners ();
|
|
1212 if (controlListeners.length is 0) return parentText;
|
|
1213 AccessibleControlEvent event = new AccessibleControlEvent (this);
|
|
1214 event.childID = id;
|
|
1215 event.result = parentText;
|
|
1216 for (int i = 0; i < controlListeners.length; i++) {
|
|
1217 controlListeners [i].getValue (event);
|
|
1218 }
|
|
1219 return event.result;
|
|
1220 }
|
|
1221
|
|
1222 AccessibleTextListener[] getTextListeners () {
|
|
1223 if (accessible is null) return new AccessibleTextListener [0];
|
|
1224 AccessibleTextListener[] result = accessible.getTextListeners ();
|
|
1225 return result !is null ? result : new AccessibleTextListener [0];
|
|
1226 }
|
|
1227
|
|
1228 package static extern(C) void gObjectClass_finalize (GObject* atkObject) {
|
|
1229 auto superType = ATK.g_type_class_peek_parent (ATK.G_OBJECT_GET_CLASS (cast(GTypeInstance*)atkObject));
|
|
1230 auto objectClassStruct = cast(GObjectClass*)ATK.G_OBJECT_CLASS (cast(GTypeClass*)superType);
|
|
1231 objectClassStruct.finalize(atkObject);
|
|
1232 AccessibleObject object = getAccessibleObject (cast(AtkObject*)atkObject);
|
|
1233 if (object !is null) {
|
|
1234 AccessibleObjects.remove (cast(AtkObject*)atkObject);
|
|
1235 object.release ();
|
|
1236 }
|
|
1237 }
|
|
1238
|
|
1239 static int nextIndexOfChar (String string, String searchChars, int startIndex) {
|
|
1240 int result = string.length;
|
|
1241 for (int i = 0; i < searchChars.length; i++) {
|
|
1242 char current = searchChars[i];
|
|
1243 int index = locate( string, current, startIndex );
|
|
1244 if (index !is string.length ) result = Math.min (result, index);
|
|
1245 }
|
|
1246 return result;
|
|
1247 }
|
|
1248
|
|
1249 static int nextIndexOfNotChar (String string, String searchChars, int startIndex) {
|
|
1250 int length = string.length;
|
|
1251 int index = startIndex;
|
|
1252 while (index < length) {
|
|
1253 char current = string[index];
|
|
1254 if ( !contains( searchChars, current)) break;
|
|
1255 index++;
|
|
1256 }
|
|
1257 return index;
|
|
1258 }
|
|
1259
|
|
1260 static int previousIndexOfChar (String string, String searchChars, int startIndex) {
|
|
1261 int result = -1;
|
|
1262 if (startIndex < 0) return result;
|
|
1263 string = string[0 .. startIndex];
|
|
1264 for (int i = 0; i < searchChars.length ; i++) {
|
|
1265 char current = searchChars[i];
|
|
1266 int index = locatePrior( string, current);
|
|
1267 if (index !is string.length ) result = Math.max (result, index);
|
|
1268 }
|
|
1269 return result;
|
|
1270 }
|
|
1271
|
|
1272 static int previousIndexOfNotChar (String string, String searchChars, int startIndex) {
|
|
1273 if (startIndex < 0) return -1;
|
|
1274 int index = startIndex - 1;
|
|
1275 while (index >= 0) {
|
|
1276 char current = string[index];
|
|
1277 if ( !contains(searchChars, current)) break;
|
|
1278 index--;
|
|
1279 }
|
|
1280 return index;
|
|
1281 }
|
|
1282
|
|
1283 void release () {
|
|
1284 if (DEBUG) getDwtLogger().info( __FILE__, __LINE__, "AccessibleObject.release: {}", handle);
|
|
1285 accessible = null;
|
|
1286 foreach( child; children ){
|
|
1287 if (child.isLightweight) OS.g_object_unref (child.handle);
|
|
1288 }
|
|
1289 if (parent !is null) parent.removeChild (this, false);
|
|
1290 }
|
|
1291
|
|
1292 void removeChild (AccessibleObject child, bool unref) {
|
|
1293 children.remove (child.handle);
|
|
1294 if (unref && child.isLightweight) OS.g_object_unref (child.handle);
|
|
1295 }
|
|
1296
|
|
1297 void selectionChanged () {
|
|
1298 OS.g_signal_emit_by_name0 (handle, ATK.selection_changed.ptr);
|
|
1299 }
|
|
1300
|
|
1301 void setFocus (int childID) {
|
|
1302 updateChildren ();
|
|
1303 AccessibleObject accObject = getChildByID (childID);
|
|
1304 if (accObject !is null) {
|
|
1305 ATK.atk_focus_tracker_notify (accObject.handle);
|
|
1306 }
|
|
1307 }
|
|
1308
|
|
1309 void setParent (AccessibleObject parent) {
|
|
1310 this.parent = parent;
|
|
1311 }
|
|
1312
|
|
1313 void textCaretMoved(int index) {
|
|
1314 OS.g_signal_emit_by_name1 (handle, ATK.text_caret_moved.ptr, index);
|
|
1315 }
|
|
1316
|
|
1317 void textChanged(int type, int startIndex, int length) {
|
|
1318 if (type is ACC.TEXT_DELETE) {
|
|
1319 OS.g_signal_emit_by_name2 (handle, ATK.text_changed_delete.ptr, startIndex, length);
|
|
1320 } else {
|
|
1321 OS.g_signal_emit_by_name2 (handle, ATK.text_changed_insert.ptr, startIndex, length);
|
|
1322 }
|
|
1323 }
|
|
1324
|
|
1325 void textSelectionChanged() {
|
|
1326 OS.g_signal_emit_by_name0 (handle, ATK.text_selection_changed.ptr);
|
|
1327 }
|
|
1328
|
|
1329 void updateChildren () {
|
|
1330 if (isLightweight) return;
|
|
1331 AccessibleControlListener[] listeners = getControlListeners ();
|
|
1332 if (listeners.length is 0) return;
|
|
1333
|
|
1334 AccessibleControlEvent event = new AccessibleControlEvent (this);
|
|
1335 for (int i = 0; i < listeners.length; i++) {
|
|
1336 listeners [i].getChildren (event);
|
|
1337 }
|
|
1338 if (event.children !is null && event.children.length > 0) {
|
|
1339 AtkObject*[] idsToKeep = new AtkObject*[]( children.length );
|
|
1340 idsToKeep.length = 0;
|
|
1341 if ( null !is (cast(Integer)event.children[0] )) {
|
|
1342 /* an array of child id's (Integers) was answered */
|
|
1343 auto parentType = AccessibleFactory.getDefaultParentType ();
|
|
1344 for (int i = 0; i < event.children.length; i++) {
|
|
1345 AccessibleObject object = getChildByIndex (i);
|
|
1346 if (object is null) {
|
|
1347 auto childType = AccessibleFactory.getChildType (accessible, i);
|
|
1348 object = new AccessibleObject (childType, null, accessible, parentType, true);
|
|
1349 AccessibleObjects[object.handle] = object;
|
|
1350 addChild (object);
|
|
1351 object.index = i;
|
|
1352 }
|
|
1353 if( auto intChild = cast(Integer)event.children[i] ){
|
|
1354 object.id = intChild.intValue ();
|
|
1355 }
|
|
1356 else {
|
|
1357 /* a non-ID value was given so don't set the ID */
|
|
1358 }
|
|
1359 idsToKeep ~= object.handle;
|
|
1360 }
|
|
1361 } else {
|
|
1362 /* an array of Accessible children was answered */
|
|
1363 int childIndex = 0;
|
|
1364 for (int i = 0; i < event.children.length; i++) {
|
|
1365 AccessibleObject object = null;
|
|
1366 if( auto accChild = cast(Accessible)event.children[i] ){
|
|
1367 object = accChild.accessibleObject;
|
|
1368 } else {
|
|
1369 /* a non-Accessible value was given so nothing to do here */
|
|
1370 }
|
|
1371 if (object !is null) {
|
|
1372 object.index = childIndex++;
|
|
1373 idsToKeep ~= object.handle;
|
|
1374 }
|
|
1375 }
|
|
1376 }
|
|
1377 /* remove old children that were not provided as children anymore */
|
|
1378 foreach( id; children.keys ){
|
|
1379 if ( !tango.core.Array.contains( idsToKeep, id )) {
|
|
1380 AccessibleObject object = cast(AccessibleObject) children[id];
|
|
1381 removeChild (object, true);
|
|
1382 }
|
|
1383 }
|
|
1384 }
|
|
1385 }
|
|
1386 }
|