eclipsecaretstyledtext

Eclipse Editor - SWT StyledText CaretListener offset not corresponding to real file line number


I am currently working on an Eclipse plugin. In order to do an action, I need to listen to the caret listener of the active tab.

public void partOpened(IWorkbenchPartReference partRef) {
    AbstractTextEditor e = (AbstractTextEditor) ((IEditorReference) partRef).getEditor(false);
    StyledText sText = ((StyledText) e.getAdapter(Control.class));

    sText.addCaretListener(new CaretListener() {

        @Override
        public void caretMoved(CaretEvent event) {
            IDocument d = e.getDocumentProvider().getDocument(e.getEditorInput());

            ... 

            int line = d.getLineOfOffset(event.caretOffset);
            Point p = sText.getLocationAtOffset(event.caretOffset);
        }
    });
}

I use this code to add the CaretListener on the latest opened tab.

The variable line is correct only when no code blocks are collapsed. In fact, the offset returned by the event is linked to the StyledText, but I'd like to get the line number of the file.

This picture shows an example of folded text. The StyledText caret offset will give me something like line 6, 7 and 8, instead of 6, 7 and 12 (like Eclipse does).

Is there a way to "transform" the StyledText offset to a "real file" offset ? I could retrieve the line as a String and find it in the file, but it sounds like a bad idea.

Thanks !


Solution

  • For folding editors the editor's source viewer will implement ITextViewerExtension5 which provides a widgetOffset2ModelOffset method to make this adjustment.

    Get the caret position using something like:

    ISourceViewer sourceViewer = e.getSourceViewer();
    
    int caret;
    if (sourceViewer instanceof ITextViewerExtension5) {
        ITextViewerExtension5 extension = (ITextViewerExtension5)sourceViewer;
        caret = extension.widgetOffset2ModelOffset(styledText.getCaretOffset());
    } else {
        int offset = sourceViewer.getVisibleRegion().getOffset();
        caret = offset + styledText.getCaretOffset();
    }