Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [platform-swt-dev] How does Accessible interface works ?


Here is a little test snippet that I had lying around. It's a Canvas with 2 colored squares on it. Each of the squares can take focus (I happened to use the tab key to traverse between them, but arrow keys is fine, too). For the role, I just randomly called them "radio buttons" because there's a "selected" one, and an "unselected" one. What kind of role do you think your widget, or its "children", should have? There are several roles on Windows that we did not implement because other platforms did not have those particular accessible roles. Here's the complete list of Windows roles, FYI. If you think one of them is important to your application, please open a bugzilla feature request against SWT and explain why you need that role.

http://msdn.microsoft.com/library/en-us/msaa/msaaccrf_4nub.asp

For some production-quality examples of custom controls that have implemented accessibile interfaces, please see CCombo, CLabel, CTabFolder, and StyledText classes in the package org.eclipse.swt.custom.

Good luck,
Carolyn

Here's the snippet:


import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.accessibility.*;

public class AccessibleShapes {
        static Display display;
        static Shell parentShell;
        static Shell shell;
        static Canvas canvas;
        static Accessible accessible;
        static int focusShape = -1;
        static final Rectangle blueBounds = new Rectangle(20, 20, 100, 100);
        static final Rectangle redBounds = new Rectangle(140, 20, 100, 100);
        static boolean dialog = false; // true for dialog, false for plain shell
       
        public static void main(String[] args) {
                display = new Display();
                if (dialog) {
                        parentShell = new Shell(display);
                        shell = new Shell(parentShell);
                } else {
                        shell = new Shell(display);
                }
                shell.setText(dialog ? "Dialog" : "Shell");
                canvas = new Canvas(shell, SWT.NONE);
                canvas.setSize(260, 140);
                accessible = canvas.getAccessible();

                canvas.addPaintListener(new PaintListener() {
                        public void paintControl(PaintEvent e) {
                                GC gc = e.gc;
                                gc.setBackground(display.getSystemColor(SWT.COLOR_BLUE));
                                gc.fillRectangle(blueBounds);
                                if (focusShape == 0) gc.drawFocus(blueBounds.x, blueBounds.y, blueBounds.width, blueBounds.height);

                                gc.setBackground(display.getSystemColor(SWT.COLOR_RED));
                                gc.fillRectangle(redBounds);
                                if (focusShape == 1) gc.drawFocus(redBounds.x, redBounds.y, redBounds.width, redBounds.height);
                        }
                });
               
                canvas.addMouseListener(new MouseAdapter() {
                        public void mouseDown(MouseEvent e) {
                                if (blueBounds.contains(e.x, e.y)) {
                                        setFocus(0);
                                } else if (redBounds.contains(e.x, e.y)) {
                                        setFocus(1);
                                } else {
                                        setFocus(-1);
                                }
                        }
                });
               
                canvas.addFocusListener(new FocusListener() {
                        public void focusGained(FocusEvent e) {
                                if (focusShape == -1) {
                                        accessible.setFocus(ACC.CHILDID_SELF);
                                } else {
                                        accessible.setFocus(focusShape);
                                }
                        }
                        public void focusLost(FocusEvent e) {
                        }
                });
               
                canvas.addTraverseListener(new TraverseListener() {
                        public void keyTraversed(TraverseEvent e) {
                                switch (e.detail) {
                                        case SWT.TRAVERSE_TAB_NEXT:
                                        case SWT.TRAVERSE_TAB_PREVIOUS:
                                                if (focusShape == 0) setFocus(1);
                                                else setFocus(0);
                                                e.doit = true;
                                                break;
                                }
                        }
                });

                accessible.addAccessibleListener(new AccessibleAdapter() {
                        public void getName(AccessibleEvent e) {
                                switch (e.childID) {
                                        case ACC.CHILDID_SELF: e.result = "Canvas"; break;
                                        case 0: e.result = "Blue"; break;
                                        case 1: e.result = "Red"; break;
                                }
                        }
                });
                accessible.addAccessibleControlListener(new AccessibleControlAdapter() {
                        public void getChildCount(AccessibleControlEvent e) {
                                e.detail = 2;
                        }
                        public void getChildren(AccessibleControlEvent e) {
                                e.children = new Integer[] {new Integer(0), new Integer(1)};
                        }
                        public void getChildAtPoint(AccessibleControlEvent e) {
                                Point pt = canvas.toControl(e.x, e.y);
                                if (blueBounds.contains(pt)) e.childID = 0;
                                else if (redBounds.contains(pt)) e.childID = 1;
                                else e.childID = ACC.CHILDID_SELF;
                        }
                        public void getFocus(AccessibleControlEvent e) {
                                if (canvas.isFocusControl()) {
                                        if (focusShape == -1) e.childID = ACC.CHILDID_SELF;
                                        else e.childID = focusShape;
                                } else {
                                        e.childID = ACC.CHILDID_NONE;
                                }
                        }
                        public void getLocation(AccessibleControlEvent e) {
                                switch (e.childID) {
                                        case ACC.CHILDID_SELF:
                                                Rectangle bounds = canvas.getBounds();
                                                e.x = bounds.x; e.y = bounds.y; e.width = bounds.width; e.height = bounds.height;
                                                break;
                                        case 0:
                                                e.x = blueBounds.x; e.y = blueBounds.y; e.width = blueBounds.width; e.height = blueBounds.height;
                                                break;
                                        case 1:
                                                e.x = redBounds.x; e.y = redBounds.y; e.width = redBounds.width; e.height = redBounds.height;
                                                break;
                                }
                        }
                        public void getRole(AccessibleControlEvent e) {
                                switch (e.childID) {
                                        case ACC.CHILDID_SELF: e.detail = ACC.ROLE_CLIENT_AREA; break;
                                        case 0: e.detail = ACC.ROLE_RADIOBUTTON; break;
                                        case 1: e.detail = ACC.ROLE_RADIOBUTTON; break;
                                }
                        }
                        public void getSelection(AccessibleControlEvent e) {
                                if (canvas.isFocusControl()) {
                                        if (focusShape == -1) e.childID = ACC.CHILDID_SELF;
                                        else e.childID = focusShape;
                                } else {
                                        e.childID = ACC.CHILDID_NONE;
                                }
                        }
                        public void getState(AccessibleControlEvent e) {
                                e.detail = ACC.STATE_FOCUSABLE;
                                if (e.childID == ACC.CHILDID_SELF) {
                                        if (canvas.isFocusControl() && focusShape == -1) e.detail |= ACC.STATE_FOCUSED;
                                } else {
                                        e.detail |= ACC.STATE_SELECTABLE;
                                        if (e.childID == focusShape) e.detail |= ACC.STATE_FOCUSED | ACC.STATE_SELECTED | ACC.STATE_CHECKED;
                                }
                        }
                        public void getValue(AccessibleControlEvent e) {
                                switch (e.childID) {
                                        case ACC.CHILDID_SELF: e.result = "none"; break;
                                        case 0: e.result = "blue"; break;
                                        case 1: e.result = "red"; break;
                                }
                        }
                });

                shell.pack();
                shell.open();
                if (dialog) {
                        parentShell.pack();
                        parentShell.open();
                        shell.setFocus();
                        shell = parentShell;
                }
                canvas.setFocus();
                while (!shell.isDisposed()) {
                        if (!display.readAndDispatch()) display.sleep();
                }
        }
       
        static void setFocus(int newFocusShape) {
                focusShape = newFocusShape;
                canvas.redraw();
                if (focusShape == -1) {
                        accessible.setFocus(ACC.CHILDID_SELF);
                } else {
                        accessible.setFocus(focusShape);
                }
        }
}





Arnaud De Muyser <ademuyser@xxxxxxxxxx>
Sent by: platform-swt-dev-admin@xxxxxxxxxxx

06/29/2004 08:29 AM

Please respond to
platform-swt-dev

To
platform-swt-dev@xxxxxxxxxxx
cc
Subject
[platform-swt-dev] How does Accessible interface works ?






Hi,


I'm trying to implement accessibility on a widget I've created (from swt.Canvas).

As I can see in Eclipse 3.0 help system I implement an "org.eclipse.swt.accessibility.AccessibleControlListener" (see below),

and I do the following to setup accessible inside my widget: "getAccessible().addAccessibleControlListener( new MyAccessible() );".


My widget contains inner rectangle which are able to get the "focus" (only one can have focus at a time),

user can give the focus from a rectangle to an other using arrows keys.

To implements full accessibility, when user change the focused rectangle, I must to make the screen reader talking new data from focused rectangle,

to do this I write the following method:

private void saidFocusedEvent()

 {

    this.getAccessible().setFocus( ACC.CHILDID_SELF );//doesn't work: this.handle );
 }


I'm using two different screen reader:

1/ first is the Microsoft's Narrator:

       If this screen reader read all tooltips I open from my widget, it never said things when I call "saidFocusedEvent" method.


2/second is Windows Eyes 4.5 SP3:

       this one tell more things than Ms'Narrator, all tooltips, all "text" I draw in my Widget,
       But it said texts only for  the first 3 call of  "saidFocusedEvent()", after that all call to "saidFocusedEvent()" are quiet ... to bad !

       (sometimes it continue to read the first texts I've returned in MyAccessible.getValue() for each "saidFocusedEvent()" call ... to bad too ).

       (when it's quiet I can see none of the trace output I wrote in method like if interface's method are never called ...).


Does anyone have experimented this kind of behaviour ?


As I'm not the only one in development team who experiment this kind of things,

I want to know where I'm wrong in my source code ?


How can I make my accessible implementation talk data when I want to do it ?


Does anyone knows what I must return in Accessible.getRole() method ? None of the constants defined in ACC class suit me...

and if I return nothing ... screen reader just said "Custom control" without said text I return in getValue()... strange ?


Any help is really welcome, thanks a lot !


Arnaud.



PS: AccessibleControlListener implementation:


private class MyAccessible
implements AccessibleControlListener
 {

   public void getRole(AccessibleControlEvent e)

   {

       e.detail=ACC.ROLE_TOOLTIP; //KO:_TABLECELL;//_SCROLLBAR;//_TOOLTIP; //_LABEL; //KO:_CLIENT_AREA;

System.out.println("[TITBW] Accessible["+this.hashCode()+"].getRole()");      

   }  
   public void getValue(AccessibleControlEvent e)
   {

     e.result =getFocusedRectangleData();

System.out.println("[TIBTW] Accessible["+this.hashCode()+"].getValue() said ?=<"+s+">");      

   }

   public void getState(AccessibleControlEvent e)

   {

     e.detail=ACC.STATE_FOCUSED ;

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getState()");      

   }

   public void getFocus( AccessibleControlEvent e)

   {

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getFocus()");

     e.detail = ACC.CHILDID_SELF;

   }

   public void getChildAtPoint(AccessibleControlEvent e) {

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getChildAtPoint()");

   }

   public void getLocation(AccessibleControlEvent e) {

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getLocation()");

   }

   public void getChild(AccessibleControlEvent e) {

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getChild()");

   }

   public void getChildCount(AccessibleControlEvent e) {

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getChildCount()");

   }

   public void getDefaultAction(AccessibleControlEvent e) {

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getDefaultAction()");

   }

   public void getSelection(AccessibleControlEvent e) {

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getSelection()");

      e.detail = ACC.CHILDID_SELF; //ThreadInfoByTimeWidget.this.handle;

   }

   public void getChildren(AccessibleControlEvent e) {

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getChildren()");

   }

 }


Back to the top