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

accessibility package
author Frank Benoit <benoit@tionex.de>
date Fri, 11 Jan 2008 05:07:22 +0100
parents
children 8f049b136add
comparison
equal deleted inserted replaced
41:c83c51423d03 42:787b5413b0ce
1 /*******************************************************************************
2 * Copyright (c) 2000, 2006 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.AccessibleFactory;
12
13
14 import dwt.internal.accessibility.gtk.ATK;
15 import dwt.internal.gtk.OS;
16 import dwt.accessibility.Accessible;
17 import dwt.accessibility.ACC;
18 import dwt.accessibility.AccessibleObject;
19 import dwt.accessibility.AccessibleControlEvent;
20 import dwt.accessibility.AccessibleControlListener;
21
22 import dwt.SWT;
23
24 import tango.stdc.stringz;
25 import tango.io.Stdout;
26
27 class AccessibleFactory {
28 AtkObjectFactory * handle;
29 uint objectParentType;
30 char* widgetTypeName;
31
32 //Callback atkObjectFactoryCB_create_accessible;
33 //Callback gTypeInfo_base_init_factory;
34 Accessible[GtkWidget*] accessibles;
35
36 static long[char[]] Types;
37 static AccessibleFactory[long] Factories;
38
39 static const uint DefaultParentType; //$NON-NLS-1$
40 static const char[] FACTORY_PARENTTYPENAME = "AtkObjectFactory";
41 static const char[] SWT_TYPE_PREFIX = "SWT";
42 static const char[] CHILD_TYPENAME = "Child";
43 static const char[] FACTORY_TYPENAME = "SWTFactory";
44 static const int[] actionRoles = [
45 ACC.ROLE_CHECKBUTTON, ACC.ROLE_COMBOBOX, ACC.ROLE_LINK,
46 ACC.ROLE_MENUITEM, ACC.ROLE_PUSHBUTTON, ACC.ROLE_RADIOBUTTON,
47 ];
48 static const int[] hypertextRoles = [ACC.ROLE_LINK];
49 static const int[] selectionRoles = [
50 ACC.ROLE_LIST, ACC.ROLE_TABFOLDER, ACC.ROLE_TABLE, ACC.ROLE_TREE,
51 ];
52 static const int[] textRoles = [
53 ACC.ROLE_COMBOBOX, ACC.ROLE_LINK, ACC.ROLE_LABEL, ACC.ROLE_TEXT,
54 ];
55
56 /* AT callbacks*/
57 /* interface definitions */
58 static GTypeInfo* ObjectIfaceDefinition;
59 static const GInterfaceInfo* ActionIfaceDefinition;
60 static const GInterfaceInfo* ComponentIfaceDefinition;
61 static const GInterfaceInfo* HypertextIfaceDefinition;
62 static const GInterfaceInfo* SelectionIfaceDefinition;
63 static const GInterfaceInfo* TextIfaceDefinition;
64
65 static this(){
66 DefaultParentType = OS.g_type_from_name ("GtkAccessible"); //$NON-NLS-1$
67 /* Action interface */
68 ActionIfaceDefinition = cast(GInterfaceInfo*)OS.g_malloc (GInterfaceInfo.sizeof);
69 ActionIfaceDefinition.interface_init = &AccessibleFactory.initActionIfaceCB;
70 /* Component interface */
71 ComponentIfaceDefinition = cast(GInterfaceInfo*)OS.g_malloc (GInterfaceInfo.sizeof);
72 ComponentIfaceDefinition.interface_init = &AccessibleFactory.initComponentIfaceCB;
73 /* Hypertext interface */
74 HypertextIfaceDefinition = cast(GInterfaceInfo*)OS.g_malloc (GInterfaceInfo.sizeof);
75 HypertextIfaceDefinition.interface_init = &AccessibleFactory.initHypertextIfaceCB;
76 /* Selection interface */
77 SelectionIfaceDefinition = cast(GInterfaceInfo*)OS.g_malloc (GInterfaceInfo.sizeof);
78 SelectionIfaceDefinition.interface_init = &AccessibleFactory.initSelectionIfaceCB;
79 /* Text interface */
80 TextIfaceDefinition =cast(GInterfaceInfo*) OS.g_malloc (GInterfaceInfo.sizeof);
81 TextIfaceDefinition.interface_init = &AccessibleFactory.initTextIfaceCB;
82 }
83
84 private this (int /*long*/ widgetType) {
85 widgetTypeName = OS.g_type_name (widgetType);
86 char[] factoryName = FACTORY_TYPENAME ~ fromUtf8z( widgetTypeName ) ~ \0;
87 if (OS.g_type_from_name (factoryName.ptr) is 0) {
88 /* register the factory */
89 auto registry = ATK.atk_get_default_registry ();
90 auto previousFactory = ATK.atk_registry_get_factory (registry, widgetType);
91 objectParentType = ATK.atk_object_factory_get_accessible_type (previousFactory);
92 if (objectParentType is 0) objectParentType = DefaultParentType;
93 auto factoryParentType = OS.g_type_from_name (FACTORY_PARENTTYPENAME.ptr);
94 auto typeInfo = cast(GTypeInfo*) OS.g_malloc (GTypeInfo.sizeof);
95 typeInfo.base_init = &gTypeInfo_base_init_factory;
96 typeInfo.class_size = AtkObjectFactoryClass.sizeof;
97 typeInfo.instance_size = AtkObjectFactory.sizeof;
98 auto swtFactoryType = OS.g_type_register_static (factoryParentType, factoryName.ptr, typeInfo, 0);
99 ATK.atk_registry_set_factory_type (registry, widgetType, swtFactoryType);
100 handle = ATK.atk_registry_get_factory (registry, widgetType);
101 }
102 }
103
104 void addAccessible (Accessible accessible) {
105 auto controlHandle = accessible.getControlHandle ();
106 accessibles[controlHandle] = accessible;
107 ATK.atk_object_factory_create_accessible (handle, cast(GObject*)controlHandle);
108 }
109
110 private static extern(C) AtkObject* atkObjectFactory_create_accessible (GObject* widget) {
111 auto widgetType = OS.G_OBJECT_TYPE ( cast(GTypeInstance*)widget);
112 if( auto factory = widgetType in Factories ){
113 with( *factory ){
114 Accessible accessible = accessibles[ cast(GtkWidget*) widget ];
115 if (accessible is null) {
116 /*
117 * we don't care about this control, so create it with the parent's
118 * type so that its accessibility callbacks will not pass though here
119 */
120 auto result = cast(AtkObject*) OS.g_object_new (objectParentType, null);
121 ATK.atk_object_initialize (result, cast(void*)widget);
122 return result;
123 }
124 /* if an atk object has already been created for this widget then just return it */
125 if (accessible.accessibleObject !is null) {
126 return accessible.accessibleObject.handle;
127 }
128 char[] buffer = fromUtf8z( widgetTypeName ).dup;
129 auto type = getType (buffer, accessible, objectParentType, ACC.CHILDID_SELF);
130 AccessibleObject object = new AccessibleObject (type, cast(GtkWidget*)widget, accessible, objectParentType, false);
131 accessible.accessibleObject = object;
132 return object.handle;
133 }
134 }
135 else{
136 Stdout.formatln( "AccessibleFactory.atkObjectFactoryCB_create_accessible cannot find factory instance" );
137 }
138 }
139
140 static int /*long*/ getChildType (Accessible accessible, int childIndex) {
141 return getType (CHILD_TYPENAME, accessible, DefaultParentType, childIndex);
142 }
143
144 static int /*long*/ getDefaultParentType () {
145 return DefaultParentType;
146 }
147
148 static int /*long*/ getType (char[] widgetTypeName, Accessible accessible, int /*long*/ parentType, int childId) {
149 AccessibleControlEvent event = new AccessibleControlEvent (accessible);
150 event.childID = childId;
151 AccessibleControlListener[] listeners = accessible.getControlListeners ();
152 for (int i = 0; i < listeners.length; i++) {
153 listeners [i].getRole (event);
154 }
155 bool action = false, hypertext = false, selection = false, text = false;
156 if (event.detail !is 0) { /* a role was specified */
157 for (int i = 0; i < actionRoles.length; i++) {
158 if (event.detail is actionRoles [i]) {
159 action = true;
160 break;
161 }
162 }
163 for (int i = 0; i < hypertextRoles.length; i++) {
164 if (event.detail is hypertextRoles [i]) {
165 hypertext = true;
166 break;
167 }
168 }
169 for (int i = 0; i < selectionRoles.length; i++) {
170 if (event.detail is selectionRoles [i]) {
171 selection = true;
172 break;
173 }
174 }
175 for (int i = 0; i < textRoles.length; i++) {
176 if (event.detail is textRoles [i]) {
177 text = true;
178 break;
179 }
180 }
181 } else {
182 action = hypertext = selection = text = true;
183 }
184 char[] swtTypeName = SWT_TYPE_PREFIX.dup;
185 swtTypeName ~= widgetTypeName;
186 if (action) swtTypeName ~= "Action"; //$NON-NLS-1$
187 if (hypertext) swtTypeName ~= "Hypertext"; //$NON-NLS-1$
188 if (selection) swtTypeName ~= "Selection"; //$NON-NLS-1$
189 if (text) swtTypeName ~= "Text"; //$NON-NLS-1$
190
191 int /*long*/ type = 0;
192 if (swtTypeName in Types ) {
193 type = Types[swtTypeName];
194 } else {
195 /* define the type */
196 GTypeQuery* query = new GTypeQuery ();
197 OS.g_type_query (parentType, query);
198
199 GTypeInfo* typeInfo = new GTypeInfo ();
200 typeInfo.base_init = &gTypeInfo_base_init_type;
201 typeInfo.class_size = query.class_size;
202 typeInfo.instance_size = query.instance_size;
203 ObjectIfaceDefinition = typeInfo;
204
205 type = OS.g_type_register_static (parentType, toStringz( swtTypeName ), ObjectIfaceDefinition, 0);
206 OS.g_type_add_interface_static (type, AccessibleObject.ATK_COMPONENT_TYPE, ComponentIfaceDefinition);
207 if (action) OS.g_type_add_interface_static (type, AccessibleObject.ATK_ACTION_TYPE, ActionIfaceDefinition);
208 if (hypertext) OS.g_type_add_interface_static (type, AccessibleObject.ATK_HYPERTEXT_TYPE, HypertextIfaceDefinition);
209 if (selection) OS.g_type_add_interface_static (type, AccessibleObject.ATK_SELECTION_TYPE, SelectionIfaceDefinition);
210 if (text) OS.g_type_add_interface_static (type, AccessibleObject.ATK_TEXT_TYPE, TextIfaceDefinition);
211 Types[swtTypeName] = type;
212 }
213 return type;
214 }
215
216 private static extern(C) void gTypeInfo_base_init_factory (void* klass) {
217 auto atkObjectFactoryClass = ATK.ATK_OBJECT_FACTORY_CLASS (klass);
218 atkObjectFactoryClass.create_accessible = &atkObjectFactory_create_accessible;
219 }
220
221 private static extern(C) void gTypeInfo_base_init_type (void* klass) {
222 auto objectClass = cast(AtkObjectClass*)klass;
223 objectClass.get_name = &AccessibleObject.atkObject_get_name;
224 objectClass.get_description = &AccessibleObject.atkObject_get_description;
225 objectClass.get_n_children = &AccessibleObject.atkObject_get_n_children;
226 objectClass.get_role = &AccessibleObject.atkObject_get_role;
227 objectClass.get_parent = &AccessibleObject.atkObject_get_parent;
228 objectClass.ref_state_set = &AccessibleObject.atkObject_ref_state_set;
229 objectClass.get_index_in_parent = &AccessibleObject.atkObject_get_index_in_parent;
230 objectClass.ref_child = &AccessibleObject.atkObject_ref_child;
231
232 GObjectClass* gObjectClass = OS.G_OBJECT_CLASS ( cast(GTypeClass*)klass);
233 gObjectClass.finalize = &AccessibleObject.gObjectClass_finalize;
234 }
235
236 private static extern(C) void initActionIfaceCB ( void* g_iface, void* iface_data ) {
237 auto iface = cast(AtkActionIface*)g_iface;
238 iface.get_keybinding = &AccessibleObject.atkAction_get_keybinding;
239 iface.get_name = &AccessibleObject.atkAction_get_name;
240 }
241
242 private static extern(C) void initComponentIfaceCB ( void* g_iface, void* iface_data ) {
243 auto iface = cast(AtkComponentIface*)g_iface;
244 iface.get_extents = &AccessibleObject.atkComponent_get_extents;
245 iface.get_position = &AccessibleObject.atkComponent_get_position;
246 iface.get_size = &AccessibleObject.atkComponent_get_size;
247 iface.ref_accessible_at_point = &AccessibleObject.atkComponent_ref_accessible_at_point;
248 }
249
250 private static extern(C) void initHypertextIfaceCB ( void* g_iface, void* iface_data ) {
251 auto iface = cast(AtkHypertextIface*)g_iface;
252 iface.get_link = &AccessibleObject.atkHypertext_get_link;
253 iface.get_link_index = &AccessibleObject.atkHypertext_get_link_index;
254 iface.get_n_links = &AccessibleObject.atkHypertext_get_n_links;
255 }
256
257 private static extern(C) void initSelectionIfaceCB ( void* g_iface, void* iface_data ) {
258 auto iface = cast(AtkSelectionIface*)g_iface;
259 iface.is_child_selected = &AccessibleObject.atkSelection_is_child_selected;
260 iface.ref_selection = &AccessibleObject.atkSelection_ref_selection;
261 }
262
263 private static extern(C) void initTextIfaceCB ( void* g_iface, void* iface_data ) {
264 auto iface = cast(AtkTextIface*)g_iface;
265 iface.get_caret_offset = &AccessibleObject.atkText_get_caret_offset;
266 iface.get_character_at_offset = &AccessibleObject.atkText_get_character_at_offset;
267 iface.get_character_count = &AccessibleObject.atkText_get_character_count;
268 iface.get_n_selections = &AccessibleObject.atkText_get_n_selections;
269 iface.get_selection = &AccessibleObject.atkText_get_selection;
270 iface.get_text = &AccessibleObject.atkText_get_text;
271 iface.get_text_after_offset = &AccessibleObject.atkText_get_text_after_offset;
272 iface.get_text_at_offset = &AccessibleObject.atkText_get_text_at_offset;
273 iface.get_text_before_offset = &AccessibleObject.atkText_get_text_before_offset;
274 }
275
276 static void registerAccessible (Accessible accessible) {
277 /* If DefaultParentType is 0 then OS accessibility is not active */
278 if (DefaultParentType is 0) return;
279 auto controlHandle = accessible.getControlHandle ();
280 auto widgetType = OS.G_OBJECT_TYPE ( cast(GTypeInstance*)controlHandle);
281 AccessibleFactory factory = Factories[widgetType];
282 if (factory is null) {
283 factory = new AccessibleFactory (widgetType);
284 Factories[widgetType] = factory;
285 }
286 factory.addAccessible (accessible);
287 }
288
289 void removeAccessible (Accessible accessible) {
290 accessibles.remove (accessible.getControlHandle ());
291 }
292
293 static void unregisterAccessible (Accessible accessible) {
294 auto controlHandle = accessible.getControlHandle ();
295 auto widgetType = OS.G_OBJECT_TYPE (cast(GTypeInstance*)controlHandle);
296 AccessibleFactory factory = Factories[widgetType];
297 if (factory !is null) {
298 factory.removeAccessible (accessible);
299 }
300 }
301 }