package org.erlide.ui.editors.erl; import java.util.ResourceBundle; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextHover; import org.eclipse.jface.text.ITextHoverExtension2; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.ITextViewerExtension2; import org.eclipse.jface.text.ITextViewerExtension4; import org.eclipse.jface.text.ITextViewerExtension5; import org.eclipse.jface.text.TextUtilities; import org.eclipse.jface.text.information.IInformationProvider; import org.eclipse.jface.text.information.IInformationProviderExtension; import org.eclipse.jface.text.information.IInformationProviderExtension2; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Point; import org.eclipse.ui.texteditor.TextEditorAction; import org.eclipse.ui.texteditor.TextOperationAction; import org.erlide.ui.editors.erl.scanner.IErlangPartitions; /** * This action behaves in two different ways: If there is no current text hover, * the javadoc is displayed using information presenter. If there is a current * text hover, it is converted into a information presenter in order to make it * sticky. */ class ShowEDocAction extends TextEditorAction { /** The wrapped text operation action. */ private final TextOperationAction fTextOperationAction; private final AbstractErlangEditor editor; final ISourceViewer sourceViewer; /** * Creates a dispatch action. * * @param resourceBundle * the resource bundle * @param prefix * the prefix * @param textOperationAction * the text operation action */ public ShowEDocAction(final AbstractErlangEditor editor, final ISourceViewer sourceViewer, final ResourceBundle resourceBundle, final String prefix, final TextOperationAction textOperationAction) { super(resourceBundle, prefix, editor); if (textOperationAction == null) { throw new IllegalArgumentException(); } this.editor = editor; this.sourceViewer = sourceViewer; fTextOperationAction = textOperationAction; } /* * @see org.eclipse.jface.action.IAction#run() */ @SuppressWarnings("synthetic-access") @Override public void run() { /** * Information provider used to present the information. * * @since 3.0 */ class InformationProvider implements IInformationProvider, IInformationProviderExtension, IInformationProviderExtension2 { private final IRegion fHoverRegion; private final String fHoverInfo; private final IInformationControlCreator fControlCreator; InformationProvider(final IRegion hoverRegion, final String hoverInfo, final IInformationControlCreator controlCreator) { fHoverRegion = hoverRegion; fHoverInfo = hoverInfo; fControlCreator = controlCreator; } /* * @seeorg.eclipse.jface.text.information.IInformationProvider# * getSubject(org.eclipse.jface.text.ITextViewer, int) */ @Override public IRegion getSubject(final ITextViewer textViewer, final int invocationOffset) { return fHoverRegion; } @Override public Object getInformation2(final ITextViewer textViewer, final IRegion subject) { return fHoverInfo; } /* * @see * org.eclipse.jface.text.information.IInformationProviderExtension2 * #getInformationPresenterControlCreator() * * @since 3.0 */ @Override public IInformationControlCreator getInformationPresenterControlCreator() { return fControlCreator; } @Override @Deprecated public String getInformation(final ITextViewer textViewer, final IRegion subject) { return null; } } if (sourceViewer == null) { fTextOperationAction.run(); return; } if (sourceViewer instanceof ITextViewerExtension4) { final ITextViewerExtension4 extension4 = (ITextViewerExtension4) sourceViewer; if (extension4.moveFocusToWidgetToken()) { return; } } if (!(sourceViewer instanceof ITextViewerExtension2)) { fTextOperationAction.run(); return; } final ITextViewerExtension2 textViewerExtension2 = (ITextViewerExtension2) sourceViewer; // does a text hover exist? final ITextHover textHover = textViewerExtension2.getCurrentTextHover(); if (textHover == null) { // TODO this crashes... why? // fTextOperationAction.run(); return; } final Point hoverEventLocation = textViewerExtension2.getHoverEventLocation(); final int offset = computeOffsetAtLocation(sourceViewer, hoverEventLocation.x, hoverEventLocation.y); if (offset == -1) { fTextOperationAction.run(); return; } try { // get the text hover content final String contentType = TextUtilities.getContentType( sourceViewer.getDocument(), IErlangPartitions.ERLANG_PARTITIONING, offset, true); final IRegion hoverRegion = textHover.getHoverRegion(sourceViewer, offset); if (hoverRegion == null) { return; } final String hoverInfo = ""; if (textHover instanceof ITextHoverExtension2) { ((ITextHoverExtension2) textHover).getHoverInfo2(sourceViewer, hoverRegion); } IInformationControlCreator controlCreator = null; if (textHover instanceof IInformationProviderExtension2) { controlCreator = ((IInformationProviderExtension2) textHover) .getInformationPresenterControlCreator(); } final IInformationProvider informationProvider = new InformationProvider( hoverRegion, hoverInfo, controlCreator); editor.fInformationPresenter.setOffset(offset); editor.fInformationPresenter .setDocumentPartitioning(IErlangPartitions.ERLANG_PARTITIONING); editor.fInformationPresenter.setInformationProvider(informationProvider, contentType); editor.fInformationPresenter.showInformation(); } catch (final BadLocationException e) { } } // modified version from TextViewer private int computeOffsetAtLocation(final ITextViewer textViewer, final int x, final int y) { final StyledText styledText = textViewer.getTextWidget(); final IDocument document = textViewer.getDocument(); if (document == null) { return -1; } try { final int widgetLocation = styledText.getOffsetAtLocation(new Point(x, y)); if (textViewer instanceof ITextViewerExtension5) { final ITextViewerExtension5 extension = (ITextViewerExtension5) textViewer; return extension.widgetOffset2ModelOffset(widgetLocation); } final IRegion visibleRegion = textViewer.getVisibleRegion(); return widgetLocation + visibleRegion.getOffset(); } catch (final IllegalArgumentException e) { return -1; } } }