Mercurial > projects > dwt-linux
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 } |