Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 329216

Summary: StyledText needs to implement AccessibleEditableTextListener
Product: [Eclipse Project] Platform Reporter: Carolyn MacLeod <carolynmacleod4>
Component: SWTAssignee: Felipe Heidrich <eclipse.felipe>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: Silenio_Quarti, skovatch
Version: 3.7   
Target Milestone: 3.7 M6   
Hardware: PC   
OS: All   
Whiteboard:
Bug Depends on:    
Bug Blocks: 324254    

Description Carolyn MacLeod CLA 2010-11-01 14:52:11 EDT
From bug 324005, StyledText needs to implement AccessibleEditableTextListener so that accessibility tools such as speech recognition systems can replace text.

It is understood that StyledText itself cannot implement the setTextAttributes method of AccessibleEditableTextListener because it is completely up to the application whether or not an "external tool" such as a speech recognition engine will be allowed to modify the styles of the text. (For example a Java Editor has its own syntax highlighting, so in that case it does not make sense for an external tool to selectively modify text styles).

Here is a Snippet that can be used as an example:

import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.accessibility.*;
import org.eclipse.swt.custom.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;

public class AccessibleEditableTextTest {
	
	public static void main(String[] args) {
		final Display display = new Display();
		Shell shell = new Shell(display);
		shell.setText("AccessibleEditableText");
		shell.setLayout(new GridLayout());
		
		final StyledText text = new StyledText(shell, SWT.BORDER | SWT.MULTI);
		text.setText("The quick brown fox jumps over the lazy dog.\nThat's all folks!");
		text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		TextStyle textStyle = new TextStyle(new Font(display, "Courier", 12, SWT.BOLD), display.getSystemColor(SWT.COLOR_RED), null);
		textStyle.strikeout = true;
		textStyle.underline = true;
		textStyle.underlineStyle = SWT.UNDERLINE_SINGLE;
		text.setStyleRanges(new int[] {4, 5}, new StyleRange[] {new StyleRange(textStyle)});

		final Text valueField = new Text(shell, SWT.MULTI | SWT.WRAP | SWT.BORDER);
		GridData data = new GridData(400, 200);
		data.horizontalAlignment = SWT.FILL;
		valueField.setLayoutData(data);
		
		text.getAccessible().addAccessibleAttributeListener(new AccessibleAttributeAdapter() {
			public void getTextAttributes(AccessibleTextAttributeEvent e) {
				valueField.setText("getTextAttributes " + e);
			}
		});

		text.getAccessible().addAccessibleEditableTextListener(new AccessibleEditableTextListener() {
			public void copyText(AccessibleEditableTextEvent e) {
				valueField.setText("copyText " + e);
				text.setSelection(e.start, e.end);
				text.copy();
				e.result = ACC.OK;
			}
			
			public void cutText(AccessibleEditableTextEvent e) {
				valueField.setText("cutText " + e);
				text.setSelection(e.start, e.end);
				text.cut();
				e.result = ACC.OK;
			}
			
			public void pasteText(AccessibleEditableTextEvent e) {
				valueField.setText("pasteText " + e);
				text.setSelection(e.start);
				text.paste();
				e.result = ACC.OK;
			}
			
			public void replaceText(AccessibleEditableTextEvent e) {
				valueField.setText("replaceText " + e);
				text.replaceTextRange(e.start, e.end - e.start, e.string);
				e.result = ACC.OK;
			}

			public void setTextAttributes(AccessibleTextAttributeEvent e) {
				valueField.setText("setTextAttributes " + e);
				TextStyle textStyle = e.textStyle;
				if (textStyle != null) {
					/* Copy all of the TextStyle fields into the new StyleRange. */
					StyleRange style = new StyleRange(textStyle);
					/* Create new graphics resources because the old ones are only valid during the event. */
					if (textStyle.font != null) style.font = new Font(display, textStyle.font.getFontData());
					if (textStyle.foreground != null) style.foreground = new Color(display, textStyle.foreground.getRGB());
					if (textStyle.background != null) style.background = new Color(display, textStyle.background.getRGB());
					if (textStyle.underlineColor != null) style.underlineColor = new Color(display, textStyle.underlineColor.getRGB());
					if (textStyle.strikeoutColor != null) style.strikeoutColor = new Color(display, textStyle.strikeoutColor.getRGB());
					if (textStyle.borderColor != null) style.borderColor = new Color(display, textStyle.borderColor.getRGB());
					/* Set the StyleRange into the StyledText. */
					style.start = e.start;
					style.length = e.end - e.start;
					text.setStyleRange(style);
					e.result = ACC.OK;
				} else {
					text.setStyleRanges(e.start, e.end - e.start, null, null);
				}
			}
		});

		shell.pack();
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) display.sleep();
		}
	}
}
Comment 1 Carolyn MacLeod CLA 2010-11-01 14:58:59 EDT
Regarding implementing setAttributes by default... at some point in the future, we could consider the possibility of having an "allow text style changes from accessibility tools" style bit (default false), so that applications that do not enforce text styles would get setAttributes behavior "for free".
Comment 2 Carolyn MacLeod CLA 2010-12-17 10:07:48 EST
Would be nice if this got in before M5, because it is how outside applications will use the new AccessibleEditableText API.

See the addAccessibleEditableTextListener code in the snippet in comment 0 for an example of how to implement.
Comment 3 Felipe Heidrich CLA 2011-01-31 10:00:37 EST
Fixed in HEAD 

Changed the implementation setTextAttributes() to do nothing, a few reason for that:
1) When StyledText has line event listener the setStyle API should not be used
2) The result of setTextAttributes could overwrite (or be overwritten) by user styles
3) The resources created in the implementation were not being freed.

For the above, we agreed that setTextAttributes has to be implemented at the application level.