| /******************************************************************************* |
| * Copyright (c) 2007, 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: |
| * Takashi ITOH - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.actf.visualization.gui.ui.views; |
| |
| import org.eclipse.actf.accservice.swtbridge.AccessibleObject; |
| import org.eclipse.actf.accservice.swtbridge.MSAA; |
| import org.eclipse.actf.ai.voice.IVoice; |
| import org.eclipse.actf.ai.voice.IVoiceEventListener; |
| import org.eclipse.actf.ai.voice.VoicePlugin; |
| import org.eclipse.actf.visualization.gui.GuiPlugin; |
| import org.eclipse.actf.visualization.gui.Messages; |
| import org.eclipse.actf.visualization.gui.preferences.GuiPreferenceConstants; |
| import org.eclipse.actf.visualization.gui.ui.actions.HideHtmlAction; |
| import org.eclipse.actf.visualization.gui.ui.actions.RefreshRootAction; |
| import org.eclipse.actf.visualization.gui.ui.actions.ShowOffscreenAction; |
| import org.eclipse.actf.visualization.gui.util.ScreenReaderRenderer; |
| import org.eclipse.actf.visualization.gui.util.TextMap; |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.action.IMenuListener; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.action.IToolBarManager; |
| import org.eclipse.jface.action.MenuManager; |
| import org.eclipse.jface.action.Separator; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.preference.PreferenceConverter; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.StyleRange; |
| import org.eclipse.swt.custom.StyledText; |
| import org.eclipse.swt.events.KeyAdapter; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.events.MouseAdapter; |
| import org.eclipse.swt.events.MouseEvent; |
| import org.eclipse.swt.events.TypedEvent; |
| import org.eclipse.swt.graphics.Font; |
| import org.eclipse.swt.graphics.FontData; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Menu; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.IActionBars; |
| import org.eclipse.ui.IWorkbenchActionConstants; |
| import org.eclipse.ui.dialogs.PreferencesUtil; |
| import org.eclipse.ui.part.ViewPart; |
| |
| |
| public class JAWSTextView extends ViewPart implements IJAWSTextView { |
| public static final String ID = JAWSTextView.class.getName(); |
| |
| private StyledText text; |
| private RefreshRootAction refreshAction; |
| private ShowOffscreenAction showOffscreenAction; |
| private HideHtmlAction hideHtmlAction; |
| private Action speakAction; |
| private Action speakAllAction; |
| private Action stopAction; |
| private Action openPreferencesAction; |
| |
| private IPreferenceStore preferenceStore = GuiPlugin.getDefault().getPreferenceStore(); |
| |
| private TextMap textMap = new TextMap(); |
| private Point lastSelection = null; |
| private boolean ignoreSelection = false; |
| |
| public void createPartControl(Composite parent) { |
| text = new StyledText(parent,SWT.WRAP | SWT.V_SCROLL | SWT.H_SCROLL){ |
| public void invokeAction(int action) { |
| super.invokeAction(action); |
| } |
| }; |
| text.setEditable(false); |
| text.setLayout(new GridLayout()); |
| text.setLayoutData(new GridData()); |
| resetFont(); |
| preferenceStore.addPropertyChangeListener(new IPropertyChangeListener() { |
| public void propertyChange(PropertyChangeEvent event) { |
| if( GuiPreferenceConstants.JAWSTextView_Font.equals(event.getProperty())) { |
| resetFont(); |
| } |
| } |
| }); |
| makeActions(); |
| hookContextMenu(); |
| contributeToActionBars(); |
| MSAAViewRegistory.findView(MSAAViewRegistory.MSAAOutlineView_ID); |
| refresh(); |
| text.addKeyListener(new KeyAdapter(){ |
| public void keyPressed(KeyEvent e) { |
| ScreenReaderRenderer.setBusy(true); |
| } |
| public void keyReleased(KeyEvent e) { |
| ScreenReaderRenderer.setBusy(true); |
| if( SWT.CR == e.keyCode ) { |
| doClick(e); |
| } |
| else if( ' ' == e.keyCode ) { |
| doSelect(e); |
| } |
| else { |
| checkSelection(e); |
| } |
| } |
| }); |
| text.setDoubleClickEnabled(false); |
| text.addMouseListener(new MouseAdapter(){ |
| public void mouseUp(MouseEvent e) { |
| if( 1 == e.button ) { |
| checkSelection(e); |
| } |
| } |
| public void mouseDoubleClick(MouseEvent e) { |
| if( 1 == e.button ) { |
| doClick(e); |
| } |
| } |
| }); |
| |
| VoicePlugin.getVoice().setEventListener(new IVoiceEventListener(){ |
| public void indexReceived(final int index) { |
| text.getDisplay().asyncExec(new Runnable(){ |
| public void run() { |
| selectLine(index); |
| }}); |
| } |
| }); |
| } |
| |
| private void checkSelection(TypedEvent event) { |
| Point newSelection = text.getSelection(); |
| if( !newSelection.equals(lastSelection) ) { |
| lastSelection = newSelection; |
| AccessibleObject accObject = textMap.getAccessibleObject(newSelection); |
| if( null != accObject ) { |
| IMSAAOutlineView outlineView = (IMSAAOutlineView)MSAAViewRegistory.findView(MSAAViewRegistory.MSAAOutlineView_ID); |
| if( null != outlineView ) { |
| ignoreSelection = true; |
| try { |
| outlineView.setSelection(accObject); |
| } |
| finally { |
| ignoreSelection = false; |
| } |
| } |
| |
| } |
| } |
| } |
| |
| private void doClick(TypedEvent event) { |
| AccessibleObject accObject = getSelectedItem(); |
| if( null != accObject ) { |
| accObject.doDefaultAction(); |
| } |
| } |
| |
| private void doSelect(TypedEvent event) { |
| AccessibleObject accObject = getSelectedItem(); |
| if( null != accObject ) { |
| accObject.select(MSAA.SELFLAG_TAKEFOCUS); |
| } |
| } |
| |
| private AccessibleObject getSelectedItem() { |
| return textMap.getAccessibleObject(text.getSelection()); |
| } |
| |
| private void resetFont() { |
| FontData fontData = PreferenceConverter.getFontData(preferenceStore,GuiPreferenceConstants.JAWSTextView_Font); |
| text.setFont(new Font(text.getDisplay(), fontData)); |
| } |
| |
| public void setFocus() { |
| text.setFocus(); |
| } |
| |
| public void setSelection(AccessibleObject object) { |
| VoicePlugin.getVoice().stop(); |
| if( ignoreSelection ) return; |
| object = MSAAViewRegistory.adjustSelection(object); |
| if( null != object ) { |
| Point point = textMap.getPoint(object); |
| if( null != point ) { |
| if( point.x == point.y ) { |
| if( point.x > 0 ) { |
| point.x--; |
| } |
| else if( point.y < text.getCharCount() ) { |
| point.y++; |
| } |
| } |
| text.setSelection(point.x,point.y); |
| } |
| } |
| } |
| |
| public void refresh() { |
| AccessibleObject object = MSAAViewRegistory.adjustSelection(null); |
| VoicePlugin.getVoice().stop(); |
| if( null == object ) { |
| setText(Messages.getString("msaa.jaws.notarget"),SWT.COLOR_DARK_GRAY); //$NON-NLS-1$ |
| } |
| else { |
| new ScreenReaderRenderer(text,textMap).renderAll(object); |
| } |
| } |
| |
| private void setText(String message, int color) { |
| text.setText(message); |
| StyleRange range = new StyleRange(); |
| range.foreground = Display.getCurrent().getSystemColor(color); |
| range.start = 0; |
| range.length = text.getCharCount(); |
| text.setStyleRange(range); |
| } |
| |
| private void selectLine(int line) { |
| if( -1 == line ) { |
| Point selection = text.getSelection(); |
| if( selection.x != selection.y ) { |
| text.setSelection(selection.y,selection.y); |
| } |
| return; |
| } |
| int start = text.getOffsetAtLine(line); |
| int end = start + text.getContent().getLine(line).length(); |
| text.setSelection(start,end); |
| } |
| |
| private void hookContextMenu() { |
| MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$ |
| menuMgr.setRemoveAllWhenShown(true); |
| menuMgr.addMenuListener(new IMenuListener() { |
| public void menuAboutToShow(IMenuManager manager) { |
| JAWSTextView.this.fillContextMenu(manager); |
| } |
| }); |
| Menu menu = menuMgr.createContextMenu(text); |
| text.setMenu(menu); |
| getSite().registerContextMenu(menuMgr, new AccessibleObjectSelectionProvider(){ |
| public Object getSelectedAccessibleObject() { |
| return getSelectedItem(); |
| } |
| }); |
| } |
| |
| private void contributeToActionBars() { |
| IActionBars bars = getViewSite().getActionBars(); |
| fillLocalPullDown(bars.getMenuManager()); |
| fillLocalToolBar(bars.getToolBarManager()); |
| } |
| |
| private void fillLocalPullDown(IMenuManager manager) { |
| manager.add(showOffscreenAction); |
| manager.add(new Separator()); |
| manager.add(hideHtmlAction); |
| manager.addMenuListener(new IMenuListener(){ |
| public void menuAboutToShow(IMenuManager manager) { |
| showOffscreenAction.adjust(); |
| hideHtmlAction.adjust(); |
| } |
| }); |
| manager.add(new Separator()); |
| manager.add(openPreferencesAction); |
| } |
| |
| private void fillContextMenu(IMenuManager manager) { |
| // Other plug-ins can contribute there actions here |
| manager.add(speakAction); |
| manager.add(new Separator()); |
| manager.add(speakAllAction); |
| manager.add(stopAction); |
| manager.add(new Separator()); |
| manager.add(refreshAction); |
| manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); |
| } |
| |
| private void fillLocalToolBar(IToolBarManager manager) { |
| manager.add(refreshAction); |
| manager.add(speakAllAction); |
| manager.add(stopAction); |
| } |
| |
| private void makeActions() { |
| refreshAction = new RefreshRootAction(); |
| showOffscreenAction = new ShowOffscreenAction(); |
| hideHtmlAction = new HideHtmlAction(); |
| |
| speakAction = new Action(Messages.getString("msaa.speak_here")) { //$NON-NLS-1$ |
| public void run() { |
| IVoice voice = VoicePlugin.getVoice(); |
| try { |
| voice.stop(); |
| int lineCount = text.getLineCount(); |
| int offset = text.getSelection().x; |
| int startLine = text.getLineAtOffset(offset); |
| for( int line = startLine; line < lineCount ;line++ ) { |
| voice.speak(text.getContent().getLine(line),false,line); |
| } |
| } |
| catch( Exception e) { |
| } |
| } |
| }; |
| speakAllAction = new Action(Messages.getString("msaa.speak")) { //$NON-NLS-1$ |
| public void run() { |
| text.setCaretOffset(0); |
| speakAction.run(); |
| } |
| }; |
| speakAllAction.setToolTipText(Messages.getString("msaa.speak_tip")); //$NON-NLS-1$ |
| speakAllAction.setImageDescriptor(GuiPlugin.IMAGE_SPEAK); |
| |
| stopAction = new Action(Messages.getString("msaa.stop")) { //$NON-NLS-1$ |
| public void run() { |
| VoicePlugin.getVoice().stop(); |
| selectLine(-1); |
| } |
| }; |
| stopAction.setToolTipText(Messages.getString("msaa.stop_tip")); //$NON-NLS-1$ |
| stopAction.setImageDescriptor(GuiPlugin.IMAGE_STOP); |
| |
| final Shell shell = this.getViewSite().getShell(); |
| openPreferencesAction = new Action(Messages.getString("msaa.preferences")) { //$NON-NLS-1$ |
| public void run() { |
| PreferencesUtil |
| .createPreferenceDialogOn(shell, "org.eclipse.actf.visualization.gui.preferences.GuiPreferencePage", null, null) //$NON-NLS-1$ |
| .open(); |
| } |
| }; |
| } |
| } |