Mercurial > projects > dwt-mac
view dwt/accessibility/Accessible.d @ 128:07399639c0c8
Added DWT extension to dwt.widgets.MessageBox
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Sat, 17 Jan 2009 16:26:49 +0100 |
parents | 63a09873578e |
children | ad4e1fe71a5a |
line wrap: on
line source
/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * * Port to the D programming language: * Jacob Carlborg <doob@me.com> *******************************************************************************/ module dwt.accessibility.Accessible; import dwt.dwthelper.utils; import dwt.DWT; import dwt.DWTException; import dwt.graphics.Point; import dwt.graphics.Rectangle; import dwt.internal.cocoa.NSArray; import dwt.internal.cocoa.NSMutableArray; import dwt.internal.cocoa.NSNumber; import dwt.internal.cocoa.NSObject; import dwt.internal.cocoa.NSPoint; import dwt.internal.cocoa.NSRange; import dwt.internal.cocoa.NSSize; import dwt.internal.cocoa.NSString; import dwt.internal.cocoa.NSValue; import dwt.internal.cocoa.OS; import cocoa = dwt.internal.cocoa.id; import dwt.widgets.Composite; import dwt.widgets.Control; import dwt.widgets.Display; import dwt.widgets.Monitor; import dwt.widgets.Shell; import tango.core.Thread; import tango.util.container.HashMap; import dwt.accessibility.ACC; import dwt.accessibility.AccessibleControlEvent; import dwt.accessibility.AccessibleEvent; import dwt.accessibility.AccessibleListener; import dwt.accessibility.AccessibleControlListener; import dwt.accessibility.AccessibleTextEvent; import dwt.accessibility.AccessibleTextListener; import dwt.accessibility.SWTAccessibleDelegate; /** * Instances of this class provide a bridge between application * code and assistive technology clients. Many platforms provide * default accessible behavior for most widgets, and this class * allows that default behavior to be overridden. Applications * can get the default Accessible object for a control by sending * it <code>getAccessible</code>, and then add an accessible listener * to override simple items like the name and help string, or they * can add an accessible control listener to override complex items. * As a rule of thumb, an application would only want to use the * accessible control listener to implement accessibility for a * custom control. * * @see Control#getAccessible * @see AccessibleListener * @see AccessibleEvent * @see AccessibleControlListener * @see AccessibleControlEvent * @see <a href="http://www.eclipse.org/swt/snippets/#accessibility">Accessibility snippets</a> * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> * * @since 2.0 */ public class Accessible { static NSString[] baseAttributes; static NSString[] baseTextAttributes; static NSString[] baseParameterizedAttributes; NSMutableArray attributeNames = null; NSMutableArray parameterizedAttributeNames = null; NSMutableArray actionNames = null; AccessibleListener[] accessibleListeners; AccessibleControlListener[] accessibleControlListeners; AccessibleTextListener[] accessibleTextListeners; Control control; HashMap!(int, SWTAccessibleDelegate) children; this (Control control) { this.control = control; baseAttributes = [ OS.NSAccessibilityRoleAttribute, OS.NSAccessibilityRoleDescriptionAttribute, OS.NSAccessibilityHelpAttribute, OS.NSAccessibilityFocusedAttribute, OS.NSAccessibilityParentAttribute, OS.NSAccessibilityChildrenAttribute, OS.NSAccessibilityPositionAttribute, OS.NSAccessibilitySizeAttribute, OS.NSAccessibilityWindowAttribute, OS.NSAccessibilityTopLevelUIElementAttribute ]; baseTextAttributes = [ OS.NSAccessibilityNumberOfCharactersAttribute, OS.NSAccessibilitySelectedTextAttribute, OS.NSAccessibilitySelectedTextRangeAttribute, OS.NSAccessibilityInsertionPointLineNumberAttribute, OS.NSAccessibilitySelectedTextRangesAttribute, OS.NSAccessibilityVisibleCharacterRangeAttribute, OS.NSAccessibilityValueAttribute ]; baseParameterizedAttributes = [ OS.NSAccessibilityStringForRangeParameterizedAttribute, OS.NSAccessibilityRangeForLineParameterizedAttribute ]; } /** * Invokes platform specific functionality to allocate a new accessible object. * <p> * <b>IMPORTANT:</b> This method is <em>not</em> part of the public * API for <code>Accessible</code>. It is marked public only so that it * can be shared within the packages provided by SWT. It is not * available on all platforms, and should never be called from * application code. * </p> * * @param control the control to get the accessible object for * @return the platform specific accessible object */ public static Accessible internal_new_Accessible(Control control) { return new Accessible(control); } /** * Adds the listener to the collection of listeners who will * be notified when an accessible client asks for certain strings, * such as name, description, help, or keyboard shortcut. The * listener is notified by sending it one of the messages defined * in the <code>AccessibleListener</code> interface. * * @param listener the listener that should be notified when the receiver * is asked for a name, description, help, or keyboard shortcut string * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleListener * @see #removeAccessibleListener */ public void addAccessibleListener (AccessibleListener listener) { checkWidget(); if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); accessibleListeners.addElement(listener); } /** * Adds the listener to the collection of listeners who will * be notified when an accessible client asks for custom control * specific information. The listener is notified by sending it * one of the messages defined in the <code>AccessibleControlListener</code> * interface. * * @param listener the listener that should be notified when the receiver * is asked for custom control specific information * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleControlListener * @see #removeAccessibleControlListener */ public void addAccessibleControlListener(AccessibleControlListener listener) { checkWidget(); if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); accessibleControlListeners.addElement(listener); } /** * Adds the listener to the collection of listeners who will * be notified when an accessible client asks for custom text control * specific information. The listener is notified by sending it * one of the messages defined in the <code>AccessibleTextListener</code> * interface. * * @param listener the listener that should be notified when the receiver * is asked for custom text control specific information * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleTextListener * @see #removeAccessibleTextListener * * @since 3.0 */ public void addAccessibleTextListener (AccessibleTextListener listener) { checkWidget (); if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); accessibleTextListeners.addElement (listener); } public cocoa.id internal_accessibilityActionDescription(NSString action, int childID) { // TODO No action support for now. return NSString.stringWith(""); } public NSArray internal_accessibilityActionNames(int childID) { // The supported action list depends on the role played by the control. AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = childID; event.detail = -1; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = elementAt(accessibleControlListeners, i); listener.getRole(event); } // No accessible listener is overriding the role of the control, so let Cocoa return the default set for the control. if (event.detail is -1) { return null; } if ((childID is ACC.CHILDID_SELF) && (actionNames !is null)) { return retainedAutoreleased(actionNames); } NSMutableArray returnValue = NSMutableArray.arrayWithCapacity(5); switch (event.detail) { case ACC.ROLE_PUSHBUTTON: case ACC.ROLE_RADIOBUTTON: case ACC.ROLE_CHECKBUTTON: case ACC.ROLE_TABITEM: returnValue.addObject(OS.NSAccessibilityPressAction); break; } switch (event.detail) { case ACC.ROLE_COMBOBOX: returnValue.addObject(OS.NSAccessibilityConfirmAction); break; } if (childID is ACC.CHILDID_SELF) { actionNames = returnValue; actionNames.retain(); return retainedAutoreleased(actionNames); } else { // Caller must retain if they want to hold on to it. return returnValue; } } public NSArray internal_accessibilityAttributeNames(int childID) { // The supported attribute set depends on the role played by the control. // We may need to add or remove from the base set as needed. AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = childID; event.detail = -1; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getRole(event); } // No accessible listener is overriding the role of the control, so let Cocoa // return the default set for the control. if (event.detail is -1) return null; if ((childID is ACC.CHILDID_SELF) && (attributeNames !is null)) { return retainedAutoreleased(attributeNames); } NSMutableArray returnValue = NSMutableArray.arrayWithCapacity(baseAttributes.length); /* Add our list of supported attributes to the array. * Make sure each attribute name is not already in the array before appending. */ for (int i = 0; i < baseAttributes.length; i++) { if (!returnValue.containsObject(baseAttributes[i])) { returnValue.addObject(baseAttributes[i]); } } if (accessibleTextListeners.size() > 0) { for (int i = 0; i < baseTextAttributes.length; i++) { if (!returnValue.containsObject(baseTextAttributes[i])) { returnValue.addObject(baseTextAttributes[i]); } } } // The following are expected to have a value (AXValue) switch (event.detail) { case ACC.ROLE_CHECKBUTTON: case ACC.ROLE_RADIOBUTTON: case ACC.ROLE_LABEL: case ACC.ROLE_TABITEM: case ACC.ROLE_TABFOLDER: returnValue.addObject(OS.NSAccessibilityValueAttribute); break; } // The following are expected to report their enabled status (AXEnabled) switch (event.detail) { case ACC.ROLE_CHECKBUTTON: case ACC.ROLE_RADIOBUTTON: case ACC.ROLE_LABEL: case ACC.ROLE_TABITEM: case ACC.ROLE_PUSHBUTTON: case ACC.ROLE_COMBOBOX: returnValue.addObject(OS.NSAccessibilityEnabledAttribute); break; } // The following are expected to report a title (AXTitle) switch (event.detail) { case ACC.ROLE_CHECKBUTTON: case ACC.ROLE_RADIOBUTTON: case ACC.ROLE_PUSHBUTTON: case ACC.ROLE_TABITEM: returnValue.addObject(OS.NSAccessibilityTitleAttribute); break; } // Accessibility verifier says these attributes must be reported for combo boxes. if (event.detail is ACC.ROLE_COMBOBOX) { returnValue.addObject(OS.NSAccessibilityExpandedAttribute); } // Accessibility verifier says these attributes must be reported for tab folders. if (event.detail is ACC.ROLE_TABFOLDER) { returnValue.addObject(OS.NSAccessibilityContentsAttribute); returnValue.addObject(OS.NSAccessibilityTabsAttribute); } /* * Only report back sub-roles when the DWT role maps to a sub-role. */ if (event.detail !is -1) { String osRole = roleToOs(event.detail); if (dwt.dwthelper.utils.indexOf(osRole, ':') is -1) returnValue.removeObject(OS.NSAccessibilitySubroleAttribute); } /* * Children never return their own children, so remove that attribute. */ if (childID !is ACC.CHILDID_SELF) { returnValue.removeObject(OS.NSAccessibilityChildrenAttribute); } if (childID is ACC.CHILDID_SELF) { attributeNames = returnValue; attributeNames.retain(); return retainedAutoreleased(attributeNames); } else { // Caller must retain if necessary. return returnValue; } } public cocoa.id internal_accessibilityAttributeValue(NSString attribute, int childID) { if (attribute.isEqualToString(OS.NSAccessibilityRoleAttribute)) return getRoleAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilitySubroleAttribute)) return getSubroleAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityRoleDescriptionAttribute)) return getRoleDescriptionAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityExpandedAttribute)) return getExpandedAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityHelpAttribute)) return getHelpAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityTitleAttribute)) return getTitleAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityValueAttribute)) return getValueAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityEnabledAttribute)) return getEnabledAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityFocusedAttribute)) return getFocusedAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityParentAttribute)) return getParentAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityChildrenAttribute)) return getChildrenAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityContentsAttribute)) return getChildrenAttribute(childID); // FIXME: There's no specific API just for tabs, which won't include the buttons (if any.) if (attribute.isEqualToString(OS.NSAccessibilityTabsAttribute)) return getTabsAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityWindowAttribute)) return getWindowAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityTopLevelUIElementAttribute)) return getTopLevelUIElementAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityPositionAttribute)) return getPositionAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilitySizeAttribute)) return getSizeAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityDescriptionAttribute)) return getDescriptionAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityNumberOfCharactersAttribute)) return getNumberOfCharactersAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilitySelectedTextAttribute)) return getSelectedTextAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilitySelectedTextRangeAttribute)) return getSelectedTextRangeAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityInsertionPointLineNumberAttribute)) return getInsertionPointLineNumberAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilitySelectedTextRangesAttribute)) return getSelectedTextRangesAttribute(childID); if (attribute.isEqualToString(OS.NSAccessibilityVisibleCharacterRangeAttribute)) return getVisibleCharacterRangeAttribute(childID); // If this object don't know how to get the value it's up to the control itself to return an attribute value. return null; } public cocoa.id internal_accessibilityAttributeValue_forParameter(NSString attribute, cocoa.id parameter, int childID) { if (attribute.isEqualToString(OS.NSAccessibilityStringForRangeParameterizedAttribute)) return getStringForRangeAttribute(parameter, childID); if (attribute.isEqualToString(OS.NSAccessibilityRangeForLineParameterizedAttribute)) return getRangeForLineParameterizedAttribute(parameter, childID); return null; } // Returns the UI Element that has the focus. You can assume that the search for the focus has already been narrowed down to the receiver. // Override this method to do a deeper search with a UIElement - e.g. a NSMatrix would determine if one of its cells has the focus. public cocoa.id internal_accessibilityFocusedUIElement(int childID) { AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = ACC.CHILDID_MULTIPLE; // set to invalid value, to test if the application sets it in getFocus() event.accessible = null; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getFocus(event); } // The listener did not respond, so let Cocoa figure it out. if (event.childID is ACC.CHILDID_MULTIPLE) return null; /* The application can optionally answer an accessible. */ if (event.accessible !is null) { return new cocoa.id(OS.NSAccessibilityUnignoredAncestor(event.accessible.control.view.id)); } /* Or the application can answer a valid child ID, including CHILDID_SELF and CHILDID_NONE. */ if (event.childID is ACC.CHILDID_SELF || event.childID is ACC.CHILDID_NONE) { return new cocoa.id(OS.NSAccessibilityUnignoredAncestor(control.view.id)); } return new cocoa.id(OS.NSAccessibilityUnignoredAncestor(childIDToOs(event.childID).id)); } // Returns the deepest descendant of the UIElement hierarchy that contains the point. // You can assume the point has already been determined to lie within the receiver. // Override this method to do deeper hit testing within a UIElement - e.g. a NSMatrix would test its cells. The point is bottom-left relative screen coordinates. public cocoa.id internal_accessibilityHitTest(NSPoint point, int childID) { AccessibleControlEvent event = new AccessibleControlEvent(this); event.x = cast(int) point.x; dwt.widgets.Monitor.Monitor primaryMonitor = Display.getCurrent().getPrimaryMonitor(); event.y = cast(int) (primaryMonitor.getBounds().height - point.y); // Set an impossible value to determine if anything responded to the event. event.childID = ACC.CHILDID_MULTIPLE; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getChildAtPoint(event); } // The listener did not respond, so let Cocoa figure it out. if (event.childID is ACC.CHILDID_MULTIPLE) return null; if (event.accessible !is null) { return new cocoa.id(OS.NSAccessibilityUnignoredAncestor(event.accessible.control.view.id)); } if (event.childID is ACC.CHILDID_SELF || event.childID is ACC.CHILDID_NONE) { return new cocoa.id(OS.NSAccessibilityUnignoredAncestor(control.view.id)); } return new cocoa.id(OS.NSAccessibilityUnignoredAncestor(childIDToOs(event.childID).id)); } public bool internal_accessibilityIsAttributeSettable(NSString attribute, int childID) { return false; } // Return YES if the UIElement doesn't show up to the outside world - i.e. its parent should return the UIElement's children as its own - cutting the UIElement out. E.g. NSControls are ignored when they are single-celled. public bool internal_accessibilityIsIgnored(int childID) { return false; } // parameterized attribute methods public NSArray internal_accessibilityParameterizedAttributeNames(int childID) { if ((childID is ACC.CHILDID_SELF) && (parameterizedAttributeNames !is null)) { return retainedAutoreleased(parameterizedAttributeNames); } NSMutableArray returnValue = NSMutableArray.arrayWithCapacity(4); if (accessibleTextListeners.size() > 0) { for (int i = 0; i < baseParameterizedAttributes.length; i++) { if (!returnValue.containsObject(baseParameterizedAttributes[i])) { returnValue.addObject(baseParameterizedAttributes[i]); } } } if (childID is ACC.CHILDID_SELF) { parameterizedAttributeNames = returnValue; parameterizedAttributeNames.retain(); return retainedAutoreleased(parameterizedAttributeNames); } else { // Caller must retain if they want to keep it. return returnValue; } } public void internal_accessibilityPerformAction(NSString action, int childID) { // TODO Auto-generated method stub // No action support for now. } /** * Returns the control for this Accessible object. * * @return the receiver's control * @since 3.0 */ public Control getControl() { return control; } /** * Invokes platform specific functionality to dispose an accessible object. * <p> * <b>IMPORTANT:</b> This method is <em>not</em> part of the public * API for <code>Accessible</code>. It is marked public only so that it * can be shared within the packages provided by DWT. It is not * available on all platforms, and should never be called from * application code. * </p> */ public void internal_dispose_Accessible() { if (actionNames !is null) actionNames.release(); actionNames = null; if (attributeNames !is null) attributeNames.release(); attributeNames = null; if (parameterizedAttributeNames !is null) parameterizedAttributeNames.release(); parameterizedAttributeNames = null; foreach (childDelegate ; children) childDelegate.internal_dispose_SWTAccessibleDelegate(); children.clear(); } cocoa.id getExpandedAttribute(int childID) { // TODO: May need to expand the API so the combo box state can be reported. return NSNumber.numberWithBool(false); } cocoa.id getHelpAttribute (int childID) { cocoa.id returnValue = null; AccessibleEvent event = new AccessibleEvent(this); event.childID = childID; for (int i = 0; i < accessibleListeners.size(); i++) { AccessibleListener listener = accessibleListeners.elementAt(i); listener.getHelp(event); } if (event.result !is null) { returnValue = NSString.stringWith(event.result); } return returnValue; } NSString getRoleAttribute(int childID) { NSString returnValue = null; AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = childID; event.detail = -1; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getRole(event); } if (event.detail !is -1) { String appRole = roleToOs (event.detail); int index = dwt.dwthelper.utils.indexOf(appRole, ':'); if (index !is -1) appRole = appRole.substring(0, index); returnValue = NSString.stringWith(appRole); } return returnValue; } cocoa.id getSubroleAttribute (int childID) { cocoa.id returnValue = null; AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = childID; event.detail = -1; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getRole(event); } if (event.detail !is -1) { String appRole = roleToOs (event.detail); int index = dwt.dwthelper.utils.indexOf(appRole, ':'); if (index !is -1) { appRole = appRole.substring(index + 1); returnValue = NSString.stringWith(appRole); } } return returnValue; } cocoa.id getRoleDescriptionAttribute (int childID) { cocoa.id returnValue = null; AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = childID; event.detail = -1; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getRole(event); } if (event.detail !is -1) { String appRole = roleToOs (event.detail); String appSubrole = null; int index = dwt.dwthelper.utils.indexOf(appRole, ':'); if (index !is -1) { appSubrole = appRole.substring(index + 1); appRole = appRole.substring(0, index); } NSString nsAppRole = NSString.stringWith(appRole); NSString nsAppSubrole = null; if (appSubrole !is null) nsAppSubrole = NSString.stringWith(appSubrole); returnValue = new NSString(OS.NSAccessibilityRoleDescription (((nsAppRole !is null) ? nsAppRole.id : null), (nsAppSubrole !is null) ? nsAppSubrole.id : null)); } return returnValue; } cocoa.id getTitleAttribute (int childID) { cocoa.id returnValue = null;//NSString.stringWith(""); /* * Feature of the Macintosh. The text of a Label is returned in its value, * not its title, so ensure that the role is not Label before asking for the title. */ AccessibleControlEvent roleEvent = new AccessibleControlEvent(this); roleEvent.childID = childID; roleEvent.detail = -1; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getRole(roleEvent); } if (roleEvent.detail !is ACC.ROLE_LABEL) { AccessibleEvent event = new AccessibleEvent(this); event.childID = childID; event.result = null; for (int i = 0; i < accessibleListeners.size(); i++) { AccessibleListener listener = accessibleListeners.elementAt(i); listener.getName(event); } if (event.result !is null) returnValue = NSString.stringWith(event.result); } return returnValue; } cocoa.id getValueAttribute (int childID) { cocoa.id returnValue = null; AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = childID; event.detail = -1; event.result = null; //TODO: could pass the OS value to the app for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getRole(event); listener.getValue(event); } int role = event.detail; String value = event.result; switch (role) { case ACC.ROLE_RADIOBUTTON: // 1 = on, 0 = off case ACC.ROLE_CHECKBUTTON: // 1 = checked, 0 = unchecked, 2 = mixed case ACC.ROLE_SCROLLBAR: // numeric value representing the position of the scroller case ACC.ROLE_SLIDER: // the value associated with the position of the slider thumb case ACC.ROLE_PROGRESSBAR: // the value associated with the fill level of the progress bar if (value !is null) { try { int number = Integer.parseInt(value); returnValue = NSNumber.numberWithInt(number); } catch (NumberFormatException ex) { if (value.equalsIgnoreCase("true")) { returnValue = NSNumber.numberWithBool(true); } else if (value.equalsIgnoreCase("false")) { returnValue = NSNumber.numberWithBool(false); } } } else { returnValue = NSNumber.numberWithBool(false); } break; case ACC.ROLE_TABFOLDER: // the accessibility object representing the currently selected tab item case ACC.ROLE_TABITEM: // 1 = selected, 0 = not selected AccessibleControlEvent ace = new AccessibleControlEvent(this); ace.childID = -4; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getSelection(ace); } if (ace.childID >= ACC.CHILDID_SELF) { if (role is ACC.ROLE_TABITEM) { returnValue = NSNumber.numberWithBool(ace.childID is childID); } else { returnValue = new cocoa.id(OS.NSAccessibilityUnignoredAncestor(childIDToOs(ace.childID).id)); } } else { returnValue = NSNumber.numberWithBool(false); } break; case ACC.ROLE_COMBOBOX: // text of the currently selected item case ACC.ROLE_TEXT: // text in the text field if (value !is null) returnValue = NSString.stringWith(value); break; case ACC.ROLE_LABEL: // text in the label /* On a Mac, the 'value' of a label is the same as the 'name' of the label. */ AccessibleEvent e = new AccessibleEvent(this); e.childID = childID; e.result = null; for (int i = 0; i < accessibleListeners.size(); i++) { AccessibleListener listener = accessibleListeners.elementAt(i); listener.getName(e); } if (e.result !is null) { returnValue = NSString.stringWith(e.result); } else { if (value !is null) returnValue = NSString.stringWith(value); } break; } return returnValue; } cocoa.id getEnabledAttribute (int childID) { AccessibleControlEvent event = new AccessibleControlEvent(this); event.detail = -1; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getState(event); } return NSNumber.numberWithBool(control.isEnabled()); } cocoa.id getFocusedAttribute (int childID) { AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = ACC.CHILDID_MULTIPLE; // set to invalid value, to test if the application sets it in getFocus() event.accessible = null; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getFocus(event); } /* The application can optionally answer an accessible. */ // FIXME: // if (event.accessible !is null) { // bool hasFocus = (event.accessible.childID is childID) && (event.accessible.control is this.control); // return NSNumber.numberWithBool(hasFocus); // } /* Or the application can answer a valid child ID, including CHILDID_SELF and CHILDID_NONE. */ if (event.childID is ACC.CHILDID_SELF) { bool hasFocus = (event.childID is childID); return NSNumber.numberWithBool(hasFocus); } if (event.childID is ACC.CHILDID_NONE) { return NSNumber.numberWithBool(false); } if (event.childID !is ACC.CHILDID_MULTIPLE) { /* Other valid childID. */ return NSNumber.numberWithBool(event.childID is childID); } // Invalid childID at this point means the application did not implement getFocus, so // let the default handler return the native focus. bool hasFocus = (this.control.view.window().firstResponder() is control.view); return NSNumber.numberWithBool(hasFocus); } cocoa.id getParentAttribute (int childID) { // Returning null here means 'let Cocoa figure it out.' if (childID is ACC.CHILDID_SELF) return null; else return new cocoa.id(OS.NSAccessibilityUnignoredAncestor(control.view.id)); } cocoa.id getChildrenAttribute (int childID) { cocoa.id returnValue = null; if (childID is ACC.CHILDID_SELF) { AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = childID; event.detail = -1; // set to impossible value to test if app resets for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getChildCount(event); } if (event.detail > 0) { for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getChildren(event); } Object [] appChildren = event.children; if (appChildren !is null && appChildren.length > 0) { /* return an NSArray of NSAccessible objects. */ NSMutableArray childArray = NSMutableArray.arrayWithCapacity(appChildren.length); for (int i = 0; i < appChildren.length; i++) { Object child = appChildren[i]; if (cast(Integer) child) { cocoa.id accChild = childIDToOs((cast(Integer)child).intValue()); childArray.addObject(accChild); } else { childArray.addObject((cast(Accessible)child).control.view); } } returnValue = new cocoa.id(OS.NSAccessibilityUnignoredChildren(childArray.id)); } } } else { // Lightweight children have no children of their own. // Don't return null if there are no children -- always return an empty array. returnValue = NSArray.array(); } // Returning null here means we want the control itself to determine its children. If the accessible listener // implemented getChildCount/getChildren, references to those objects would have been returned above. return returnValue; } cocoa.id getTabsAttribute (int childID) { cocoa.id returnValue = null; if (childID is ACC.CHILDID_SELF) { AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = childID; event.detail = -1; // set to impossible value to test if app resets for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getChildCount(event); } if (event.detail > 0) { for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getChildren(event); } Object [] appChildren = event.children; if (appChildren !is null && appChildren.length > 0) { /* return an NSArray of NSAccessible objects. */ NSMutableArray childArray = NSMutableArray.arrayWithCapacity(appChildren.length); for (int i = 0; i < appChildren.length; i++) { Object child = appChildren[i]; if (cast(Integer)child) { int subChildID = (cast(Integer)child).intValue(); event.childID = subChildID; event.detail = -1; for (int j = 0; j < accessibleControlListeners.size(); j++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(j); listener.getRole(event); } if (event.detail is ACC.ROLE_TABITEM) { cocoa.id accChild = childIDToOs((cast(Integer)child).intValue()); childArray.addObject(accChild); } } else { childArray.addObject((cast(Accessible)child).control.view); } } returnValue = new cocoa.id(OS.NSAccessibilityUnignoredChildren(childArray.id)); } } } else { // Lightweight children have no children of their own. // Don't return null if there are no children -- always return an empty array. returnValue = NSArray.array(); } // Returning null here means we want the control itself to determine its children. If the accessible listener // implemented getChildCount/getChildren, references to those objects would have been returned above. return returnValue; } cocoa.id getWindowAttribute (int childID) { return control.view.window(); } cocoa.id getTopLevelUIElementAttribute (int childID) { return control.view.window(); } cocoa.id getPositionAttribute (int childID) { cocoa.id returnValue = null; AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = childID; event.width = -1; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getLocation(event); } dwt.widgets.Monitor.Monitor primaryMonitor = Display.getCurrent().getPrimaryMonitor(); NSPoint osPositionAttribute = NSPoint (); if (event.width !is -1) { // The point returned is the lower-left coordinate of the widget in lower-left relative screen coordinates. osPositionAttribute.x = event.x; osPositionAttribute.y = primaryMonitor.getBounds().height - event.y - event.height; returnValue = NSValue.valueWithPoint(osPositionAttribute); } else { if (childID !is ACC.CHILDID_SELF) { Point pt = null; Rectangle location = control.getBounds(); if (control.getParent() !is null) pt = control.getParent().toDisplay(location.x, location.y); else pt = (cast(Shell)control).toDisplay(location.x, location.y); osPositionAttribute.x = pt.x; osPositionAttribute.y = pt.y; returnValue = NSValue.valueWithPoint(osPositionAttribute); } } return returnValue; } cocoa.id getSizeAttribute (int childID) { cocoa.id returnValue = null; AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = childID; event.width = -1; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getLocation(event); } NSSize controlSize = NSSize (); if (event.width !is -1) { controlSize.width = event.width; controlSize.height = event.height; returnValue = NSValue.valueWithSize(controlSize); } else { if (childID !is ACC.CHILDID_SELF) { controlSize.width = controlSize.height = 0; returnValue = NSValue.valueWithSize(controlSize); } } return returnValue; } cocoa.id getDescriptionAttribute (int childID) { AccessibleEvent event = new AccessibleEvent(this); event.childID = childID; event.result = null; cocoa.id returnValue = null; for (int i = 0; i < accessibleListeners.size(); i++) { AccessibleListener listener = accessibleListeners.elementAt(i); listener.getDescription(event); } returnValue = (event.result !is null ? NSString.stringWith(event.result) : null); // If no description was provided, try the name. if (returnValue is null) { if (cast(Composite) control) returnValue = NSString.stringWith(""); } return returnValue; } cocoa.id getInsertionPointLineNumberAttribute (int childID) { cocoa.id returnValue = null; AccessibleControlEvent controlEvent = new AccessibleControlEvent(this); controlEvent.childID = childID; controlEvent.result = null; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getValue(controlEvent); } AccessibleTextEvent textEvent = new AccessibleTextEvent(this); textEvent.childID = childID; textEvent.offset = -1; for (int i = 0; i < accessibleTextListeners.size(); i++) { AccessibleTextListener listener = accessibleTextListeners.elementAt(i); listener.getCaretOffset(textEvent); } if (controlEvent.result !is null && textEvent.offset !is -1) { int lineNumber = lineNumberForOffset (controlEvent.result, textEvent.offset); returnValue = NSNumber.numberWithInt(lineNumber); } return returnValue; } cocoa.id getNumberOfCharactersAttribute (int childID) { cocoa.id returnValue = null; AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = childID; event.result = null; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getValue(event); } String appValue = event.result; if (appValue !is null) { returnValue = NSNumber.numberWithInt(appValue.length()); } return returnValue; } cocoa.id getRangeForLineParameterizedAttribute (cocoa.id parameter, int childID) { cocoa.id returnValue = null; // The parameter is an NSNumber with the line number. NSNumber lineNumberObj = new NSNumber(parameter.id); int lineNumber = lineNumberObj.intValue(); System.out_.println("Line number = " ~ Integer.toString(lineNumber)); AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = childID; event.result = null; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getValue(event); } if (event.result !is null) { NSRange range = rangeForLineNumber (lineNumber, event.result); if (range.location !is -1) { returnValue = NSValue.valueWithRange(range); } } return returnValue; } cocoa.id getSelectedTextAttribute (int childID) { cocoa.id returnValue = NSString.stringWith(""); AccessibleTextEvent event = new AccessibleTextEvent(this); event.childID = childID; event.offset = -1; event.length = -1; for (int i = 0; i < accessibleTextListeners.size(); i++) { AccessibleTextListener listener = accessibleTextListeners.elementAt(i); listener.getSelectionRange(event); } int offset = event.offset; int length = event.length; if (offset !is -1 && length !is -1 && length !is 0) { // TODO: do we need the && length !is 0 ? AccessibleControlEvent event2 = new AccessibleControlEvent(this); event2.childID = event.childID; event2.result = null; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getValue(event2); } String appValue = event2.result; if (appValue !is null) { returnValue = NSString.stringWith(appValue.substring(offset, offset + length)); } } return returnValue; } cocoa.id getSelectedTextRangeAttribute (int childID) { cocoa.id returnValue = null; AccessibleTextEvent event = new AccessibleTextEvent(this); event.childID = childID; event.offset = -1; event.length = 0; for (int i = 0; i < accessibleTextListeners.size(); i++) { AccessibleTextListener listener = accessibleTextListeners.elementAt(i); listener.getSelectionRange(event); } if (event.offset !is -1) { NSRange range = NSRange(); range.location = event.offset; range.length = event.length; returnValue = NSValue.valueWithRange(range); } return returnValue; } cocoa.id getStringForRangeAttribute (cocoa.id parameter, int childID) { cocoa.id returnValue = null; // Parameter is an NSRange wrapped in an NSValue. NSValue parameterObject = new NSValue(parameter.id); NSRange range = parameterObject.rangeValue(); AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = childID; event.result = null; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getValue(event); } String appValue = event.result; if (appValue !is null) { returnValue = NSString.stringWith(appValue.substring(range.location, range.location + range.length)); } return returnValue; } cocoa.id getSelectedTextRangesAttribute (int childID) { NSMutableArray returnValue = null; AccessibleTextEvent event = new AccessibleTextEvent(this); event.childID = childID; event.offset = -1; event.length = 0; for (int i = 0; i < accessibleTextListeners.size(); i++) { AccessibleTextListener listener = accessibleTextListeners.elementAt(i); listener.getSelectionRange(event); } if (event.offset !is -1) { returnValue = NSMutableArray.arrayWithCapacity(1); NSRange range = NSRange(); range.location = event.offset; range.length = event.length; returnValue.addObject(NSValue.valueWithRange(range)); } return returnValue; } cocoa.id getVisibleCharacterRangeAttribute (int childID) { AccessibleControlEvent event = new AccessibleControlEvent(this); event.childID = childID; event.result = null; for (int i = 0; i < accessibleControlListeners.size(); i++) { AccessibleControlListener listener = accessibleControlListeners.elementAt(i); listener.getValue(event); } NSRange range = NSRange(); if (event.result !is null) { range.location = 0; range.length = event.result.length(); } else { return null; // range.location = range.length = 0; } return NSValue.valueWithRange(range); } int lineNumberForOffset (String text, int offset) { int lineNumber = 1; int length = text.length(); for (int i = 0; i < offset; i++) { switch (text.charAt (i)) { case '\r': if (i + 1 < length) { if (text.charAt (i + 1) is '\n') ++i; } // FALL THROUGH case '\n': lineNumber++; } } return lineNumber; } NSRange rangeForLineNumber (int lineNumber, String text) { NSRange range = NSRange(); range.location = -1; int line = 1; int count = 0; int length = text.length (); for (int i = 0; i < length; i++) { if (line is lineNumber) { if (count is 0) { range.location = i; } count++; } if (line > lineNumber) break; switch (text.charAt (i)) { case '\r': if (i + 1 < length && text.charAt (i + 1) is '\n') i++; // FALL THROUGH case '\n': line++; } } range.length = count; return range; } /** * Removes the listener from the collection of listeners who will * be notified when an accessible client asks for certain strings, * such as name, description, help, or keyboard shortcut. * * @param listener the listener that should no longer be notified when the receiver * is asked for a name, description, help, or keyboard shortcut string * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleListener * @see #addAccessibleListener */ public void removeAccessibleListener(AccessibleListener listener) { checkWidget(); if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); accessibleListeners.removeElement(listener); } /** * Removes the listener from the collection of listeners who will * be notified when an accessible client asks for custom control * specific information. * * @param listener the listener that should no longer be notified when the receiver * is asked for custom control specific information * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleControlListener * @see #addAccessibleControlListener */ public void removeAccessibleControlListener(AccessibleControlListener listener) { checkWidget(); if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); accessibleControlListeners.removeElement(listener); } /** * Removes the listener from the collection of listeners who will * be notified when an accessible client asks for custom text control * specific information. * * @param listener the listener that should no longer be notified when the receiver * is asked for custom text control specific information * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see AccessibleTextListener * @see #addAccessibleTextListener * * @since 3.0 */ public void removeAccessibleTextListener (AccessibleTextListener listener) { checkWidget (); if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); accessibleTextListeners.removeElement (listener); } static NSArray retainedAutoreleased(NSArray inObject) { cocoa.id temp = inObject.retain(); cocoa.id temp2 = (new NSObject(temp.id)).autorelease(); return new NSArray(temp2.id); } /** * Sends a message to accessible clients that the child selection * within a custom container control has changed. * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @since 3.0 */ public void selectionChanged () { checkWidget(); OS.NSAccessibilityPostNotification(control.view.id, OS.NSAccessibilitySelectedChildrenChangedNotification.id); } /** * Sends a message to accessible clients indicating that the focus * has changed within a custom control. * * @param childID an identifier specifying a child of the control * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> */ public void setFocus(int childID) { checkWidget(); OS.NSAccessibilityPostNotification(control.view.id, OS.NSAccessibilityFocusedUIElementChangedNotification.id); } /** * Sends a message to accessible clients that the text * caret has moved within a custom control. * * @param index the new caret index within the control * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @since 3.0 */ public void textCaretMoved (int index) { checkWidget(); OS.NSAccessibilityPostNotification(control.view.id, OS.NSAccessibilitySelectedTextChangedNotification.id); } /** * Sends a message to accessible clients that the text * within a custom control has changed. * * @param type the type of change, one of <code>ACC.NOTIFY_TEXT_INSERT</code> * or <code>ACC.NOTIFY_TEXT_DELETE</code> * @param startIndex the text index within the control where the insertion or deletion begins * @param length the non-negative length in characters of the insertion or deletion * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @see ACC#TEXT_INSERT * @see ACC#TEXT_DELETE * * @since 3.0 */ public void textChanged (int type, int startIndex, int length) { checkWidget(); OS.NSAccessibilityPostNotification(control.view.id, OS.NSAccessibilityValueChangedNotification.id); } /** * Sends a message to accessible clients that the text * selection has changed within a custom control. * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li> * </ul> * * @since 3.0 */ public void textSelectionChanged () { checkWidget(); OS.NSAccessibilityPostNotification(control.view.id, OS.NSAccessibilitySelectedTextChangedNotification.id); } cocoa.id childIDToOs(int childID) { if (childID is ACC.CHILDID_SELF) { return control.view; } /* Check cache for childID, if found, return corresponding osChildID. */ SWTAccessibleDelegate childRef = children[childID]; if (childRef is null) { childRef = new SWTAccessibleDelegate(this, childID); children.add(childID, childRef); } return childRef; } NSString concatStringsAsRole(NSString str1, NSString str2) { NSString returnValue = str1; returnValue = returnValue.stringByAppendingString(NSString.stringWith(":")); returnValue = returnValue.stringByAppendingString(str2); return returnValue; } String roleToOs(int role) { NSString nsReturnValue = null; //OS.NSAccessibilityUnknownRole; switch (role) { case ACC.ROLE_CLIENT_AREA: nsReturnValue = OS.NSAccessibilityGroupRole; break; case ACC.ROLE_WINDOW: nsReturnValue = OS.NSAccessibilityWindowRole; break; case ACC.ROLE_MENUBAR: nsReturnValue = OS.NSAccessibilityMenuBarRole; break; case ACC.ROLE_MENU: nsReturnValue = OS.NSAccessibilityMenuRole; break; case ACC.ROLE_MENUITEM: nsReturnValue = OS.NSAccessibilityMenuItemRole; break; case ACC.ROLE_SEPARATOR: nsReturnValue = OS.NSAccessibilitySplitterRole; break; case ACC.ROLE_TOOLTIP: nsReturnValue = OS.NSAccessibilityHelpTagRole; break; case ACC.ROLE_SCROLLBAR: nsReturnValue = OS.NSAccessibilityScrollBarRole; break; case ACC.ROLE_DIALOG: nsReturnValue = concatStringsAsRole(OS.NSAccessibilityWindowRole, OS.NSAccessibilityDialogSubrole); break; case ACC.ROLE_LABEL: nsReturnValue = OS.NSAccessibilityStaticTextRole; break; case ACC.ROLE_PUSHBUTTON: nsReturnValue = OS.NSAccessibilityButtonRole; break; case ACC.ROLE_CHECKBUTTON: nsReturnValue = OS.NSAccessibilityCheckBoxRole; break; case ACC.ROLE_RADIOBUTTON: nsReturnValue = OS.NSAccessibilityRadioButtonRole; break; case ACC.ROLE_COMBOBOX: nsReturnValue = OS.NSAccessibilityComboBoxRole; break; case ACC.ROLE_TEXT: { int style = control.getStyle(); if ((style & DWT.MULTI) !is 0) { nsReturnValue = OS.NSAccessibilityTextAreaRole; } else { nsReturnValue = OS.NSAccessibilityTextFieldRole; } break; } case ACC.ROLE_TOOLBAR: nsReturnValue = OS.NSAccessibilityToolbarRole; break; case ACC.ROLE_LIST: nsReturnValue = OS.NSAccessibilityOutlineRole; break; case ACC.ROLE_LISTITEM: nsReturnValue = OS.NSAccessibilityStaticTextRole; break; case ACC.ROLE_TABLE: nsReturnValue = OS.NSAccessibilityTableRole; break; case ACC.ROLE_TABLECELL: nsReturnValue = concatStringsAsRole(OS.NSAccessibilityRowRole, OS.NSAccessibilityTableRowSubrole); break; case ACC.ROLE_TABLECOLUMNHEADER: nsReturnValue = OS.NSAccessibilitySortButtonRole; break; case ACC.ROLE_TABLEROWHEADER: nsReturnValue = concatStringsAsRole(OS.NSAccessibilityRowRole, OS.NSAccessibilityTableRowSubrole); break; case ACC.ROLE_TREE: nsReturnValue = OS.NSAccessibilityOutlineRole; break; case ACC.ROLE_TREEITEM: nsReturnValue = concatStringsAsRole(OS.NSAccessibilityOutlineRole, OS.NSAccessibilityOutlineRowSubrole); break; case ACC.ROLE_TABFOLDER: nsReturnValue = OS.NSAccessibilityTabGroupRole; break; case ACC.ROLE_TABITEM: nsReturnValue = OS.NSAccessibilityRadioButtonRole; break; case ACC.ROLE_PROGRESSBAR: nsReturnValue = OS.NSAccessibilityProgressIndicatorRole; break; case ACC.ROLE_SLIDER: nsReturnValue = OS.NSAccessibilitySliderRole; break; case ACC.ROLE_LINK: nsReturnValue = OS.NSAccessibilityLinkRole; break; } return nsReturnValue.getString(); } int osToRole(NSString osRole) { if (osRole is null) return 0; if (osRole.isEqualToString(OS.NSAccessibilityWindowRole)) return ACC.ROLE_WINDOW; if (osRole.isEqualToString(OS.NSAccessibilityMenuBarRole)) return ACC.ROLE_MENUBAR; if (osRole.isEqualToString(OS.NSAccessibilityMenuRole)) return ACC.ROLE_MENU; if (osRole.isEqualToString(OS.NSAccessibilityMenuItemRole)) return ACC.ROLE_MENUITEM; if (osRole.isEqualToString(OS.NSAccessibilitySplitterRole)) return ACC.ROLE_SEPARATOR; if (osRole.isEqualToString(OS.NSAccessibilityHelpTagRole)) return ACC.ROLE_TOOLTIP; if (osRole.isEqualToString(OS.NSAccessibilityScrollBarRole)) return ACC.ROLE_SCROLLBAR; if (osRole.isEqualToString(OS.NSAccessibilityScrollAreaRole)) return ACC.ROLE_LIST; if (osRole.isEqualToString(concatStringsAsRole(OS.NSAccessibilityWindowRole, OS.NSAccessibilityDialogSubrole))) return ACC.ROLE_DIALOG; if (osRole.isEqualToString(concatStringsAsRole(OS.NSAccessibilityWindowRole, OS.NSAccessibilitySystemDialogSubrole))) return ACC.ROLE_DIALOG; if (osRole.isEqualToString(OS.NSAccessibilityStaticTextRole)) return ACC.ROLE_LABEL; if (osRole.isEqualToString(OS.NSAccessibilityButtonRole)) return ACC.ROLE_PUSHBUTTON; if (osRole.isEqualToString(OS.NSAccessibilityCheckBoxRole)) return ACC.ROLE_CHECKBUTTON; if (osRole.isEqualToString(OS.NSAccessibilityRadioButtonRole)) return ACC.ROLE_RADIOBUTTON; if (osRole.isEqualToString(OS.NSAccessibilityComboBoxRole)) return ACC.ROLE_COMBOBOX; if (osRole.isEqualToString(OS.NSAccessibilityTextFieldRole)) return ACC.ROLE_TEXT; if (osRole.isEqualToString(OS.NSAccessibilityTextAreaRole)) return ACC.ROLE_TEXT; if (osRole.isEqualToString(OS.NSAccessibilityToolbarRole)) return ACC.ROLE_TOOLBAR; if (osRole.isEqualToString(OS.NSAccessibilityListRole)) return ACC.ROLE_LIST; if (osRole.isEqualToString(OS.NSAccessibilityTableRole)) return ACC.ROLE_TABLE; if (osRole.isEqualToString(OS.NSAccessibilityColumnRole)) return ACC.ROLE_TABLECOLUMNHEADER; if (osRole.isEqualToString(concatStringsAsRole(OS.NSAccessibilityButtonRole, OS.NSAccessibilitySortButtonRole))) return ACC.ROLE_TABLECOLUMNHEADER; if (osRole.isEqualToString(concatStringsAsRole(OS.NSAccessibilityRowRole, OS.NSAccessibilityTableRowSubrole))) return ACC.ROLE_TABLEROWHEADER; if (osRole.isEqualToString(OS.NSAccessibilityOutlineRole)) return ACC.ROLE_TREE; if (osRole.isEqualToString(concatStringsAsRole(OS.NSAccessibilityOutlineRole, OS.NSAccessibilityOutlineRowSubrole))) return ACC.ROLE_TREEITEM; if (osRole.isEqualToString(OS.NSAccessibilityTabGroupRole)) return ACC.ROLE_TABFOLDER; if (osRole.isEqualToString(OS.NSAccessibilityProgressIndicatorRole)) return ACC.ROLE_PROGRESSBAR; if (osRole.isEqualToString(OS.NSAccessibilitySliderRole)) return ACC.ROLE_SLIDER; if (osRole.isEqualToString(OS.NSAccessibilityLinkRole)) return ACC.ROLE_LINK; return ACC.ROLE_CLIENT_AREA; } /* checkWidget was copied from Widget, and rewritten to work in this package */ void checkWidget () { if (!isValidThread ()) DWT.error (DWT.ERROR_THREAD_INVALID_ACCESS); if (control.isDisposed ()) DWT.error (DWT.ERROR_WIDGET_DISPOSED); } /* isValidThread was copied from Widget, and rewritten to work in this package */ bool isValidThread () { return control.getDisplay ().getThread () is Thread.getThis (); } }