view dwt/accessibility/SWTAccessibleDelegate.d @ 45:d8635bb48c7c

Merge with SWT 3.5
author Jacob Carlborg <doob@me.com>
date Mon, 01 Dec 2008 17:07:00 +0100
parents
children cfa563df4fdd
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
 *******************************************************************************/
module dwt.accessibility.SWTAccessibleDelegate;

import dwt.dwthelper.utils;


import dwt.DWT;
import dwt.internal.C;
import dwt.internal.Callback;
import dwt.internal.cocoa.NSArray;
import dwt.internal.cocoa.NSObject;
import dwt.internal.cocoa.NSPoint;
import dwt.internal.cocoa.NSString;
import dwt.internal.cocoa.OS;
import dwt.internal.cocoa.id;

class SWTAccessibleDelegate extends NSObject {

    /**
     * Accessible Key: The string constant for looking up the accessible 
     * for a control using <code>getData(String)</code>. When an accessible
     * is created for a control, it is stored as a property in the control 
     * using <code>setData(String, Object)</code>.
     */
    static final String ACCESSIBLE_KEY = "Accessible"; //$NON-NLS-1$
    static final String DWT_OBJECT = "DWT_OBJECT";

    static Callback accessible2Args, accessible3Args, accessible4Args;
    static int /*long*/ proc2Args, proc3Args, proc4Args;

    Accessible accessibleParent;
    int /*long*/ delegateJniRef;
    int childID;

    NSArray attributeNames = null;
    NSArray parameterizedAttributeNames = null;
    NSArray actionNames = null;

    static {
        Class clazz = SWTAccessibleDelegate.class;

        accessible2Args = new Callback(clazz, "accessibleProc", 2);
        proc2Args = accessible2Args.getAddress();
        if (proc2Args is 0) DWT.error (DWT.ERROR_NO_MORE_CALLBACKS);

        accessible3Args = new Callback(clazz, "accessibleProc", 3);
        proc3Args = accessible3Args.getAddress();
        if (proc3Args is 0) DWT.error (DWT.ERROR_NO_MORE_CALLBACKS);        

        accessible4Args = new Callback(clazz, "accessibleProc", 4);
        proc4Args = accessible3Args.getAddress();
        if (proc4Args is 0) DWT.error (DWT.ERROR_NO_MORE_CALLBACKS);        

        // Accessible custom controls need to implement the NSAccessibility protocol. To do that, 
        // we dynamically add the methods to the control's class that are required 
        // by NSAccessibility. Then, when external assistive technology services are used, 
        // those methods get called to provide the needed information.

        String className = "SWTAccessibleDelegate";

        // TODO: These should either move out of Display or be accessible to this class.
        String types = "*";
        int size = C.PTR_SIZEOF, align = C.PTR_SIZEOF is 4 ? 2 : 3;

        int /*long*/ cls = OS.objc_allocateClassPair(OS.class_NSObject, className, 0);
        OS.class_addIvar(cls, DWT_OBJECT, size, (byte)align, types);

        // Add the NSAccessibility overrides
        OS.class_addMethod(cls, OS.sel_accessibilityActionNames, proc2Args, "@:");
        OS.class_addMethod(cls, OS.sel_accessibilityAttributeNames, proc2Args, "@:");
        OS.class_addMethod(cls, OS.sel_accessibilityParameterizedAttributeNames, proc2Args, "@:");
        OS.class_addMethod(cls, OS.sel_accessibilityIsIgnored, proc2Args, "@:");
        OS.class_addMethod(cls, OS.sel_accessibilityFocusedUIElement, proc2Args, "@:");

        OS.class_addMethod(cls, OS.sel_accessibilityAttributeValue_, proc3Args, "@:@");
        OS.class_addMethod(cls, OS.sel_accessibilityHitTest_, proc3Args, "@:{NSPoint}");
        OS.class_addMethod(cls, OS.sel_accessibilityIsAttributeSettable_, proc3Args, "@:@");
        OS.class_addMethod(cls, OS.sel_accessibilityActionDescription_, proc3Args, "@:@");
        OS.class_addMethod(cls, OS.sel_accessibilityPerformAction_, proc3Args, "@:@");

        OS.class_addMethod(cls, OS.sel_accessibilityAttributeValue_forParameter_, proc4Args, "@:@@");
        OS.class_addMethod(cls, OS.sel_accessibilitySetValue_forAttribute_, proc4Args, "@:@@");

        OS.objc_registerClassPair(cls);
    }


    public SWTAccessibleDelegate(Accessible accessible, int childID) {
        super(0);
        this.accessibleParent = accessible;
        this.childID = childID;
        alloc().init();
        delegateJniRef = OS.NewGlobalRef(this);
        if (delegateJniRef is 0) DWT.error(DWT.ERROR_NO_HANDLES);
        OS.object_setInstanceVariable(this.id, DWT_OBJECT, delegateJniRef);
    }

    NSArray accessibilityActionNames() {
        
        if (actionNames !is null)
            return retainedAutoreleased(actionNames);
        
        actionNames = accessibleParent.internal_accessibilityActionNames(childID);
        actionNames.retain();
        return retainedAutoreleased(actionNames);
    }

    NSArray accessibilityAttributeNames() {
        
        if (attributeNames !is null)
            return retainedAutoreleased(attributeNames);
        
        attributeNames = accessibleParent.internal_accessibilityAttributeNames(childID);
        attributeNames.retain();
        return retainedAutoreleased(attributeNames);
    }

    id accessibilityAttributeValue(NSString attribute) {
        return accessibleParent.internal_accessibilityAttributeValue(attribute, childID);
    }
    
    // parameterized attribute methods
    NSArray accessibilityParameterizedAttributeNames() {
        
        if (parameterizedAttributeNames !is null)
            return retainedAutoreleased(parameterizedAttributeNames);
        
        parameterizedAttributeNames = accessibleParent.internal_accessibilityParameterizedAttributeNames(childID);
        parameterizedAttributeNames.retain();
        return retainedAutoreleased(parameterizedAttributeNames);
    }
    
    id accessibilityAttributeValue_forParameter(NSString attribute, id parameter) {
        return accessibleParent.internal_accessibilityAttributeValue_forParameter(attribute, parameter, childID);
    }

    // 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.
    bool accessibilityIsIgnored() {
        return accessibleParent.internal_accessibilityIsIgnored(childID);
    }

    bool accessibilityIsAttributeSettable(NSString attribute) {
        return accessibleParent.internal_accessibilityIsAttributeSettable(attribute, childID);
    }

    // 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.
    id accessibilityHitTest(NSPoint point) {
        return accessibleParent.internal_accessibilityHitTest(point, childID);
    }

    // Returns the UI Element that has the focus. You can assume that the search for the focus has already been narrowed down to the reciever. 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.
    id accessibilityFocusedUIElement() {
        return accessibleParent.internal_accessibilityFocusedUIElement(childID);
    }

    void accessibilityPerformAction(NSString action) {
        accessibleParent.internal_accessibilityPerformAction(action, childID);
    }
    
    id accessibilityActionDescription(NSString action) {
        return accessibleParent.internal_accessibilityActionDescription(action, childID);
    }
    
    
    void accessibilitySetValue_forAttribute(id value, NSString attribute) {
        // This shouldn't be called!
        System.out.println("Ignoring attribute: " + attribute.getString());
    }
    
    static NSArray retainedAutoreleased(NSArray inObject) {
        id temp = inObject.retain();
        id temp2 = new NSObject(temp.id).autorelease();
        return new NSArray(temp2.id);
    }
    
    static int /*long*/ accessibleProc(int /*long*/ id, int /*long*/ sel) {
        SWTAccessibleDelegate swtAcc = getAccessibleDelegate(id);
        if (swtAcc is null) return 0;
        
        if (sel is OS.sel_accessibilityAttributeNames) {
            NSArray retObject = swtAcc.accessibilityAttributeNames();
            return (retObject is null ? 0 : retObject.id);
        } else if (sel is OS.sel_accessibilityActionNames) {
            NSArray retObject = swtAcc.accessibilityActionNames();
            return (retObject is null ? 0 : retObject.id);
        } else if (sel is OS.sel_accessibilityParameterizedAttributeNames) {
            NSArray retObject = swtAcc.accessibilityParameterizedAttributeNames();
            return (retObject is null ? 0 : retObject.id);
        } else if (sel is OS.sel_accessibilityIsIgnored) {
            bool retVal = swtAcc.accessibilityIsIgnored();
            return (retVal ? 1 : 0);
        } else if (sel is OS.sel_accessibilityFocusedUIElement) {
            id retObject = swtAcc.accessibilityFocusedUIElement();
            return (retObject is null ? 0 : retObject.id);
        }

        return 0;
    }

    static int /*long*/ accessibleProc(int /*long*/ id, int /*long*/ sel, int /*long*/ arg0) {
        SWTAccessibleDelegate swtAcc = getAccessibleDelegate(id);
        if (swtAcc is null) return 0;
        
        if (sel is OS.sel_accessibilityAttributeValue_) {
            NSString attribute = new NSString(arg0);
            id retObject = swtAcc.accessibilityAttributeValue(attribute);
            return (retObject is null ? 0 : retObject.id);
        } else if (sel is OS.sel_accessibilityHitTest_) {
            NSPoint point= new NSPoint();
            OS.memmove(point, arg0, NSPoint.sizeof);
            id retObject = swtAcc.accessibilityHitTest(point);
            return (retObject is null ? 0 : retObject.id);
        } else if (sel is OS.sel_accessibilityIsAttributeSettable_) {
            NSString attribute = new NSString(arg0);
            return (swtAcc.accessibilityIsAttributeSettable(attribute) ? 1 : 0);
        } else if (sel is OS.sel_accessibilityActionDescription_) {
            NSString action = new NSString(arg0);
            id retObject = swtAcc.accessibilityActionDescription(action);
            return (retObject is null ? 0 : retObject.id);
        } else if (sel is OS.sel_accessibilityPerformAction_) {
            NSString action = new NSString(arg0);
            swtAcc.accessibilityPerformAction(action);
        }

        return 0;
    }

    static int /*long*/ accessibleProc(int /*long*/ id, int /*long*/ sel, int /*long*/ arg0, int /*long*/ arg1) {
        SWTAccessibleDelegate swtAcc = getAccessibleDelegate(id);
        if (swtAcc is null) return 0;
        
        if (sel is OS.sel_accessibilityAttributeValue_forParameter_) {
            NSString attribute = new NSString(arg0);
            id parameter = new id(arg1);
            id retObject = swtAcc.accessibilityAttributeValue_forParameter(attribute, parameter);
            return (retObject is null ? 0 : retObject.id);
        } else if (sel is OS.sel_accessibilitySetValue_forAttribute_) {
            id value = new id(arg0);
            NSString attribute = new NSString(arg1);
            swtAcc.accessibilitySetValue_forAttribute(value, attribute);
        }

        return 0;
    }

    static SWTAccessibleDelegate getAccessibleDelegate(int /*long*/ id) {
        if (id is 0) return null;
        int /*long*/ [] jniRef = new int /*long*/ [1];
        OS.object_getInstanceVariable(id, DWT_OBJECT, jniRef);
        if (jniRef[0] is 0) return null;
        return (SWTAccessibleDelegate)OS.JNIGetObject(jniRef[0]);
    }

    public void internal_dispose_SWTAccessibleDelegate() {
        if (actionNames !is null) actionNames.release();
        actionNames = null;
        if (attributeNames !is null) attributeNames.release();
        attributeNames = null;
        if (parameterizedAttributeNames !is null) parameterizedAttributeNames.release();
        parameterizedAttributeNames = null;     
    }

}