org.eclipse.papyrus.documentation.view.SpellingTextComposite.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.papyrus.documentation.view.SpellingTextComposite.java

Source

/*****************************************************************************
 * Copyright (c) 2010 Atos Origin.
 *
 *    
 * 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:
 *  Jeremie Belmudes (Atos Origin) Jeremie.Belmudes@atosorigin.com - Initial API and implementation
 *
 *****************************************************************************/
package org.eclipse.papyrus.documentation.view;

import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;

import org.eclipse.core.commands.IHandler;
import org.eclipse.core.expressions.EvaluationResult;
import org.eclipse.core.expressions.Expression;
import org.eclipse.core.expressions.IEvaluationContext;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.SubMenuManager;
import org.eclipse.jface.commands.ActionHandler;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.AnnotationModel;
import org.eclipse.jface.text.source.IAnnotationAccess;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.ActiveShellExpression;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
import org.eclipse.ui.handlers.IHandlerActivation;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
import org.eclipse.ui.texteditor.AnnotationPreference;
import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.eclipse.ui.texteditor.MarkerAnnotationPreferences;
import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;

/**
 * A composite used to edit some documentation in a plain text mode working with the eclipse spell checking tool.<br>
 * Creation : 2 july 2010<br>
 * 
 * @author jbelmudes
 */
public class SpellingTextComposite extends Composite implements IText, Observer {

    protected StyledText fTextField; // updated only by modify events

    protected SourceViewer sourceViewer;

    protected Document document;

    protected final static String CURRENT_LINE = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE;

    protected final static String CURRENT_LINE_COLOR = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE_COLOR;

    private IHandlerActivation quickFixhandlerActivation;

    /**
     * @param composite the parent of this Composite
     */
    public SpellingTextComposite(final Composite composite) {
        this(composite, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL, false);
    }

    /**
     * @param composite the parent of this Composite
     * @param style the style of the text control
     */
    public SpellingTextComposite(final Composite composite, int style) {
        this(composite, style, false);
    }

    /**
     * @param composite the parent of this Composite
     * @param style the style of the text control
     * @param colored tells if the widget has a colored line where the cursor is set
     */
    public SpellingTextComposite(final Composite composite, int style, boolean colored) {
        super(composite, SWT.BORDER);
        this.setLayout(new FillLayout());
        AnnotationModel annotationModel = new AnnotationModel();
        IAnnotationAccess annotationAccess = new DefaultMarkerAnnotationAccess();

        sourceViewer = new SourceViewer(this, null, null, true, style);
        fTextField = sourceViewer.getTextWidget();

        final SourceViewerDecorationSupport support = new SourceViewerDecorationSupport(sourceViewer, null,
                annotationAccess, EditorsUI.getSharedTextColors());
        // display or not a colored line where the field is edited
        if (colored) {
            support.setCursorLinePainterPreferenceKeys(CURRENT_LINE, CURRENT_LINE_COLOR);
        }
        Iterator<?> e = new MarkerAnnotationPreferences().getAnnotationPreferences().iterator();
        while (e.hasNext())
            support.setAnnotationPreference((AnnotationPreference) e.next());

        support.install(EditorsUI.getPreferenceStore());

        final IHandlerService handlerService = (IHandlerService) PlatformUI.getWorkbench()
                .getService(IHandlerService.class);

        final ActionHandler quickFixActionHandler = createQuickFixActionHandler(sourceViewer);

        final TextViewerAction cutAction = new TextViewerAction(sourceViewer, ITextOperationTarget.CUT);
        cutAction.setText(Messages.SpellingTextComposite_cut);
        cutAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_CUT);

        final TextViewerAction copyAction = new TextViewerAction(sourceViewer, ITextOperationTarget.COPY);
        copyAction.setText(Messages.SpellingTextComposite_copy);
        copyAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_COPY);

        final TextViewerAction pasteAction = new TextViewerAction(sourceViewer, ITextOperationTarget.PASTE);
        pasteAction.setText(Messages.SpellingTextComposite_paste);
        pasteAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_PASTE);

        final TextViewerAction selectAllAction = new TextViewerAction(sourceViewer,
                ITextOperationTarget.SELECT_ALL);
        selectAllAction.setText(Messages.SpellingTextComposite_selectAll);
        selectAllAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_SELECT_ALL);

        final MenuManager contextMenu = new MenuManager();
        contextMenu.add(cutAction);
        contextMenu.add(copyAction);
        contextMenu.add(pasteAction);
        contextMenu.add(selectAllAction);
        contextMenu.add(new Separator());
        final SubMenuManager quickFixMenu = new SubMenuManager(contextMenu);
        quickFixMenu.setVisible(true);
        quickFixMenu.addMenuListener(new IMenuListener() {

            public void menuAboutToShow(IMenuManager manager) {
                quickFixMenu.removeAll();
                if (fTextField != null && fTextField.getEditable()) {
                    IAnnotationModel annotationModel = sourceViewer.getAnnotationModel();
                    Iterator<?> annotationIterator = annotationModel.getAnnotationIterator();
                    while (annotationIterator.hasNext()) {
                        Annotation annotation = (Annotation) annotationIterator.next();
                        if (!annotation.isMarkedDeleted()
                                && includes(annotationModel.getPosition(annotation),
                                        sourceViewer.getTextWidget().getCaretOffset())
                                && sourceViewer.getQuickAssistAssistant().canFix(annotation)) {
                            ICompletionProposal[] computeQuickAssistProposals = sourceViewer
                                    .getQuickAssistAssistant().getQuickAssistProcessor()
                                    .computeQuickAssistProposals(sourceViewer.getQuickAssistInvocationContext());
                            for (int i = 0; i < computeQuickAssistProposals.length; i++) {
                                final ICompletionProposal proposal = computeQuickAssistProposals[i];
                                quickFixMenu.add(new Action(proposal.getDisplayString()) {

                                    /*
                                     * (non-Javadoc)
                                     * 
                                     * @see org.eclipse.jface.action.Action#run()
                                     */
                                    public void run() {
                                        proposal.apply(sourceViewer.getDocument());
                                    }

                                    /*
                                     * (non-Javadoc)
                                     * 
                                     * @see org.eclipse.jface.action.Action#getImageDescriptor()
                                     */
                                    public ImageDescriptor getImageDescriptor() {
                                        if (proposal.getImage() != null) {
                                            return ImageDescriptor.createFromImage(proposal.getImage());
                                        }
                                        return null;
                                    }
                                });
                            }
                        }
                    }
                }
            }

        });

        fTextField.addFocusListener(new FocusListener() {
            private IHandlerActivation cutHandlerActivation;
            private IHandlerActivation copyHandlerActivation;
            private IHandlerActivation pasteHandlerActivation;
            private IHandlerActivation selectAllHandlerActivation;

            public void focusGained(FocusEvent e) {
                cutAction.update();
                copyAction.update();
                IHandlerService service = (IHandlerService) PlatformUI.getWorkbench()
                        .getService(IHandlerService.class);
                this.cutHandlerActivation = service.activateHandler(IWorkbenchCommandConstants.EDIT_CUT,
                        new ActionHandler(cutAction), new ActiveShellExpression(getShell()));
                this.copyHandlerActivation = service.activateHandler(IWorkbenchCommandConstants.EDIT_COPY,
                        new ActionHandler(copyAction), new ActiveShellExpression(getShell()));
                this.pasteHandlerActivation = service.activateHandler(IWorkbenchCommandConstants.EDIT_PASTE,
                        new ActionHandler(pasteAction), new ActiveShellExpression(getShell()));
                this.selectAllHandlerActivation = service.activateHandler(
                        IWorkbenchCommandConstants.EDIT_SELECT_ALL, new ActionHandler(selectAllAction),
                        new ActiveShellExpression(getShell()));
                quickFixhandlerActivation = installQuickFixActionHandler(handlerService, sourceViewer,
                        quickFixActionHandler);

            }

            /*
             * (non-Javadoc)
             * 
             * @see org.eclipse.swt.events.FocusAdapter#focusLost(org.eclipse.swt.events.FocusEvent)
             */
            public void focusLost(FocusEvent e) {
                IHandlerService service = (IHandlerService) PlatformUI.getWorkbench()
                        .getService(IHandlerService.class);
                if (quickFixhandlerActivation != null) {
                    service.deactivateHandler(quickFixhandlerActivation);
                }

                if (cutHandlerActivation != null) {
                    service.deactivateHandler(cutHandlerActivation);
                }

                if (copyHandlerActivation != null) {
                    service.deactivateHandler(copyHandlerActivation);
                }

                if (pasteHandlerActivation != null) {
                    service.deactivateHandler(pasteHandlerActivation);
                }

                if (selectAllHandlerActivation != null) {
                    service.deactivateHandler(selectAllHandlerActivation);
                }
            }

        });

        sourceViewer.addSelectionChangedListener(new ISelectionChangedListener() {

            public void selectionChanged(SelectionChangedEvent event) {
                cutAction.update();
                copyAction.update();
            }

        });

        sourceViewer.getTextWidget().addDisposeListener(new DisposeListener() {

            public void widgetDisposed(DisposeEvent e) {
                support.uninstall();
                if (quickFixhandlerActivation != null) {
                    handlerService.deactivateHandler(quickFixhandlerActivation);
                }
            }

        });

        document = new Document();

        // NOTE: Configuration must be applied before the document is set in order for
        // Hyperlink coloring to work. (Presenter needs document object up front)
        sourceViewer.configure(new TextSourceViewerConfiguration(EditorsUI.getPreferenceStore()));
        sourceViewer.setDocument(document, annotationModel);
        fTextField.setMenu(contextMenu.createContextMenu(fTextField));
    }

    protected boolean includes(Position position, int caretOffset) {
        return position.includes(caretOffset) || (position.offset + position.length) == caretOffset;
    }

    /**
     * Set the color of the texte area background
     */
    public void setBackground(Color object) {
        fTextField.setBackground(object);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.widgets.Control#setForeground(org.eclipse.swt.graphics.Color)
     */
    public void setForeground(Color color) {
        fTextField.setForeground(color);
    }

    /**
     * Installs the quick fix action handler and returns the handler activation.
     * 
     * @param handlerService the handler service
     * @param sourceViewer the source viewer
     * @param createQuickFixActionHandler
     * @return the handler activation
     * @since 3.4
     */
    private IHandlerActivation installQuickFixActionHandler(IHandlerService handlerService,
            SourceViewer sourceViewer, IHandler createQuickFixActionHandler) {

        return handlerService.activateHandler(ITextEditorActionDefinitionIds.QUICK_ASSIST,
                createQuickFixActionHandler, AlwaysTrue.INSTANCE
        /*
         * ,/*, new ActiveShellExpression(sourceViewer.getTextWidget().getShell())
         */);
    }

    /**
     * Creates and returns a quick fix action handler.
     * 
     * @param textOperationTarget the target for text operations
     * @since 3.4
     */
    private ActionHandler createQuickFixActionHandler(final ITextOperationTarget textOperationTarget) {
        Action quickFixAction = new Action() {
            /*
             * (non-Javadoc)
             * 
             * @see org.eclipse.jface.action.Action#run()
             */
            public void run() {
                textOperationTarget.doOperation(ISourceViewer.QUICK_ASSIST);
            }
        };
        quickFixAction.setActionDefinitionId(ITextEditorActionDefinitionIds.QUICK_ASSIST);
        return new ActionHandler(quickFixAction);
    }

    public void setEnabled(boolean enabled) {
        fTextField.setEditable(enabled);
        if (!enabled) {
            fTextField.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY));
        } else {
            fTextField.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_WIDGET_FOREGROUND));
        }
    }

    public void update(Observable o, Object arg) {
        if (arg instanceof String) {
            setText((String) arg); // triggers a modify event
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.topcased.tabbedproperties.sections.widgets.IText#getText()
     */
    public String getText() {
        return document.get();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.topcased.tabbedproperties.sections.widgets.IText#getControl()
     */
    public Control getControl() {
        return this;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.topcased.tabbedproperties.sections.widgets.IText#getTextControl()
     */
    public Control getTextControl() {
        return fTextField;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.topcased.tabbedproperties.sections.widgets.IText#setEditable(boolean)
     */
    public void setEditable(boolean isChangeable) {
        fTextField.setEditable(isChangeable);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.topcased.tabbedproperties.sections.widgets.IText#setText(java.lang.String)
     */
    public void setText(String string) {
        document.set(string);
    }

    private static class AlwaysTrue extends Expression {
        public static final AlwaysTrue INSTANCE = new AlwaysTrue();

        private AlwaysTrue() {
        }

        @Override
        public EvaluationResult evaluate(IEvaluationContext context) throws CoreException {
            return EvaluationResult.TRUE;
        }

    }

}