private void addProposals(final SubMenuManager quickFixMenu) {
    IAnnotationModel sourceModel = sourceViewer.getAnnotationModel();
    Iterator annotationIterator = sourceModel.getAnnotationIterator();
    while (annotationIterator.hasNext()) {
      Annotation annotation = (Annotation) annotationIterator.next();
      boolean isDeleted = annotation.isMarkedDeleted();
      boolean isIncluded =
          includes(sourceModel.getPosition(annotation), getTextWidget().getCaretOffset());
      boolean isFixable = sourceViewer.getQuickAssistAssistant().canFix(annotation);
      if (!isDeleted && isIncluded && isFixable) {
        IQuickAssistProcessor processor =
            sourceViewer.getQuickAssistAssistant().getQuickAssistProcessor();
        IQuickAssistInvocationContext context = sourceViewer.getQuickAssistInvocationContext();
        ICompletionProposal[] proposals = processor.computeQuickAssistProposals(context);

        for (ICompletionProposal proposal : proposals)
          quickFixMenu.add(createQuickFixAction(proposal));
      }
    }
  }
  /** Notifies the listener that the menu is about to be shown. */
  public void menuAboutToShow(IMenuManager mgr) {
    registerE4Support();

    // Add this menu as a visible menu.
    final IWorkbenchPartSite site = part.getSite();
    if (site != null) {
      final IWorkbench workbench = site.getWorkbenchWindow().getWorkbench();
      if (workbench instanceof Workbench) {
        final Workbench realWorkbench = (Workbench) workbench;
        runCleanUp(realWorkbench);
        ISelection input = null;
        if ((bitSet & INCLUDE_EDITOR_INPUT) != 0) {
          if (part instanceof IEditorPart) {
            final IEditorPart editorPart = (IEditorPart) part;
            input = new StructuredSelection(new Object[] {editorPart.getEditorInput()});
          }
        }
        ISelection s = (selProvider == null ? null : selProvider.getSelection());
        realWorkbench.addShowingMenus(getMenuIds(), s, input);
      }
    }

    addMenuContributions(mgr);

    readStaticActions();
    // test for additions removed to comply with menu contributions
    if (menuWrapper != null) {
      mgr = menuWrapper;
      menuWrapper.removeAll();
    }
    if ((bitSet & INCLUDE_EDITOR_INPUT) != 0) {
      addEditorActions(mgr);
    }
    addObjectActions(mgr);
    addStaticActions(mgr);
  }
  /**
   * Construct a new menu extender.
   *
   * @param id the menu id
   * @param menu the menu to extend
   * @param prov the selection provider
   * @param part the part to extend
   * @param includeEditorInput Whether the editor input should be included when adding object
   *     contributions to this context menu.
   */
  public PopupMenuExtender(
      final String id,
      final MenuManager menu,
      final ISelectionProvider prov,
      final IWorkbenchPart part,
      final boolean includeEditorInput) {
    super();
    this.menu = menu;
    this.selProvider = prov;
    this.part = part;
    this.modelPart = (MPart) part.getSite().getService(MPart.class);
    if (includeEditorInput) {
      bitSet |= INCLUDE_EDITOR_INPUT;
    }
    menu.addMenuListener(this);
    if (!menu.getRemoveAllWhenShown()) {
      menuWrapper = new SubMenuManager(menu);
      menuWrapper.setVisible(true);
    }
    createModelFor(id);
    addMenuId(id);

    Platform.getExtensionRegistry().addRegistryChangeListener(this);
  }
  private void configureContextMenu() {
    final boolean editable = isEditable(sourceViewer);
    final TextViewerAction cutAction;
    final TextViewerAction undoAction;
    final TextViewerAction redoAction;
    final TextViewerAction pasteAction;
    if (editable) {
      cutAction = new TextViewerAction(sourceViewer, ITextOperationTarget.CUT);
      cutAction.setText(UIText.SpellCheckingMessageArea_cut);
      cutAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_CUT);

      undoAction = new TextViewerAction(sourceViewer, ITextOperationTarget.UNDO);
      undoAction.setText(UIText.SpellcheckableMessageArea_undo);
      undoAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_UNDO);

      redoAction = new TextViewerAction(sourceViewer, ITextOperationTarget.REDO);
      redoAction.setText(UIText.SpellcheckableMessageArea_redo);
      redoAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_REDO);

      pasteAction = new TextViewerAction(sourceViewer, ITextOperationTarget.PASTE);
      pasteAction.setText(UIText.SpellCheckingMessageArea_paste);
      pasteAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_PASTE);
    } else {
      cutAction = null;
      undoAction = null;
      redoAction = null;
      pasteAction = null;
    }

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

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

    final TextEditorPropertyAction showWhitespaceAction =
        new TextEditorPropertyAction(
            UIText.SpellcheckableMessageArea_showWhitespace,
            sourceViewer,
            AbstractTextEditor.PREFERENCE_SHOW_WHITESPACE_CHARACTERS) {

          private IPainter whitespaceCharPainter;

          @Override
          public void propertyChange(PropertyChangeEvent event) {
            String property = event.getProperty();
            if (property.equals(getPreferenceKey())
                || AbstractTextEditor.PREFERENCE_SHOW_LEADING_SPACES.equals(property)
                || AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_SPACES.equals(property)
                || AbstractTextEditor.PREFERENCE_SHOW_TRAILING_SPACES.equals(property)
                || AbstractTextEditor.PREFERENCE_SHOW_LEADING_IDEOGRAPHIC_SPACES.equals(property)
                || AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_IDEOGRAPHIC_SPACES.equals(property)
                || AbstractTextEditor.PREFERENCE_SHOW_TRAILING_IDEOGRAPHIC_SPACES.equals(property)
                || AbstractTextEditor.PREFERENCE_SHOW_LEADING_TABS.equals(property)
                || AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_TABS.equals(property)
                || AbstractTextEditor.PREFERENCE_SHOW_TRAILING_TABS.equals(property)
                || AbstractTextEditor.PREFERENCE_SHOW_CARRIAGE_RETURN.equals(property)
                || AbstractTextEditor.PREFERENCE_SHOW_LINE_FEED.equals(property)
                || AbstractTextEditor.PREFERENCE_WHITESPACE_CHARACTER_ALPHA_VALUE.equals(
                    property)) {
              synchronizeWithPreference();
            }
          }

          @Override
          protected void toggleState(boolean checked) {
            if (checked) installPainter();
            else uninstallPainter();
          }

          /** Installs the painter on the viewer. */
          private void installPainter() {
            Assert.isTrue(whitespaceCharPainter == null);
            ITextViewer v = getTextViewer();
            if (v instanceof ITextViewerExtension2) {
              IPreferenceStore store = getStore();
              whitespaceCharPainter =
                  new WhitespaceCharacterPainter(
                      v,
                      store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_LEADING_SPACES),
                      store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_SPACES),
                      store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_TRAILING_SPACES),
                      store.getBoolean(
                          AbstractTextEditor.PREFERENCE_SHOW_LEADING_IDEOGRAPHIC_SPACES),
                      store.getBoolean(
                          AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_IDEOGRAPHIC_SPACES),
                      store.getBoolean(
                          AbstractTextEditor.PREFERENCE_SHOW_TRAILING_IDEOGRAPHIC_SPACES),
                      store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_LEADING_TABS),
                      store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_ENCLOSED_TABS),
                      store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_TRAILING_TABS),
                      store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_CARRIAGE_RETURN),
                      store.getBoolean(AbstractTextEditor.PREFERENCE_SHOW_LINE_FEED),
                      store.getInt(AbstractTextEditor.PREFERENCE_WHITESPACE_CHARACTER_ALPHA_VALUE));
              ((ITextViewerExtension2) v).addPainter(whitespaceCharPainter);
            }
          }

          /** Remove the painter from the viewer. */
          private void uninstallPainter() {
            if (whitespaceCharPainter == null) return;
            ITextViewer v = getTextViewer();
            if (v instanceof ITextViewerExtension2)
              ((ITextViewerExtension2) v).removePainter(whitespaceCharPainter);
            whitespaceCharPainter.deactivate(true);
            whitespaceCharPainter = null;
          }
        };

    MenuManager contextMenu = new MenuManager();
    if (cutAction != null) contextMenu.add(cutAction);
    contextMenu.add(copyAction);
    if (pasteAction != null) contextMenu.add(pasteAction);
    contextMenu.add(selectAllAction);
    if (undoAction != null) contextMenu.add(undoAction);
    if (redoAction != null) contextMenu.add(redoAction);
    contextMenu.add(new Separator());
    contextMenu.add(showWhitespaceAction);
    contextMenu.add(new Separator());

    if (editable) {
      final SubMenuManager quickFixMenu = new SubMenuManager(contextMenu);
      quickFixMenu.setVisible(true);
      quickFixMenu.addMenuListener(
          new IMenuListener() {
            @Override
            public void menuAboutToShow(IMenuManager manager) {
              quickFixMenu.removeAll();
              addProposals(quickFixMenu);
            }
          });
    }

    final StyledText textWidget = getTextWidget();
    textWidget.setMenu(contextMenu.createContextMenu(textWidget));

    textWidget.addFocusListener(
        new FocusListener() {

          private IHandlerActivation cutHandlerActivation;
          private IHandlerActivation copyHandlerActivation;
          private IHandlerActivation pasteHandlerActivation;
          private IHandlerActivation selectAllHandlerActivation;
          private IHandlerActivation undoHandlerActivation;
          private IHandlerActivation redoHandlerActivation;
          private IHandlerActivation quickFixHandlerActivation;
          private IHandlerActivation contentAssistHandlerActivation;

          @Override
          public void focusGained(FocusEvent e) {
            IHandlerService service = getHandlerService();
            if (service == null) return;

            if (cutAction != null) {
              cutAction.update();
              cutHandlerActivation =
                  service.activateHandler(
                      IWorkbenchCommandConstants.EDIT_CUT,
                      new ActionHandler(cutAction),
                      new ActiveShellExpression(getParent().getShell()));
            }
            copyAction.update();

            copyHandlerActivation =
                service.activateHandler(
                    IWorkbenchCommandConstants.EDIT_COPY,
                    new ActionHandler(copyAction),
                    new ActiveShellExpression(getParent().getShell()));
            if (pasteAction != null)
              this.pasteHandlerActivation =
                  service.activateHandler(
                      IWorkbenchCommandConstants.EDIT_PASTE,
                      new ActionHandler(pasteAction),
                      new ActiveShellExpression(getParent().getShell()));
            selectAllHandlerActivation =
                service.activateHandler(
                    IWorkbenchCommandConstants.EDIT_SELECT_ALL,
                    new ActionHandler(selectAllAction),
                    new ActiveShellExpression(getParent().getShell()));
            if (undoAction != null)
              undoHandlerActivation =
                  service.activateHandler(
                      IWorkbenchCommandConstants.EDIT_UNDO,
                      new ActionHandler(undoAction),
                      new ActiveShellExpression(getParent().getShell()));
            if (redoAction != null)
              redoHandlerActivation =
                  service.activateHandler(
                      IWorkbenchCommandConstants.EDIT_REDO,
                      new ActionHandler(redoAction),
                      new ActiveShellExpression(getParent().getShell()));
            if (quickFixActionHandler != null)
              quickFixHandlerActivation =
                  getHandlerService()
                      .activateHandler(
                          quickFixActionHandler.getAction().getActionDefinitionId(),
                          quickFixActionHandler,
                          new ActiveShellExpression(getParent().getShell()));
            if (contentAssistActionHandler != null)
              contentAssistHandlerActivation =
                  getHandlerService()
                      .activateHandler(
                          contentAssistActionHandler.getAction().getActionDefinitionId(),
                          contentAssistActionHandler,
                          new ActiveShellExpression(getParent().getShell()));
          }

          @Override
          public void focusLost(FocusEvent e) {
            IHandlerService service = getHandlerService();
            if (service == null) return;

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

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

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

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

            if (undoHandlerActivation != null) service.deactivateHandler(undoHandlerActivation);

            if (redoHandlerActivation != null) service.deactivateHandler(redoHandlerActivation);

            if (quickFixHandlerActivation != null)
              service.deactivateHandler(quickFixHandlerActivation);

            if (contentAssistHandlerActivation != null)
              service.deactivateHandler(contentAssistHandlerActivation);
          }
        });

    sourceViewer.addSelectionChangedListener(
        new ISelectionChangedListener() {

          @Override
          public void selectionChanged(SelectionChangedEvent event) {
            if (cutAction != null) cutAction.update();
            copyAction.update();
          }
        });

    if (editable) {
      sourceViewer.addTextListener(
          new ITextListener() {
            @Override
            public void textChanged(TextEvent event) {
              if (undoAction != null) undoAction.update();
              if (redoAction != null) redoAction.update();
            }
          });
    }

    textWidget.addDisposeListener(
        new DisposeListener() {
          @Override
          public void widgetDisposed(DisposeEvent disposeEvent) {
            showWhitespaceAction.dispose();
          }
        });
  }