Lii
Lii

Reputation: 12112

Caret position of Eclipse text editor

I'm writing a little plugin to move the caret position of an Eclipse text editor to the other side of a selected block. Problem is that I don't find a nice way to discover whether the selection is left-to-right or right-to-left.

I understand there are these alternatives:

Can't I get the caret position from my ITextEditor or ISelectionProvider or something?

Here is my code:

public class SwapCursorSelectionHandler extends AbstractHandler {
    public Object execute( ExecutionEvent event )
    {
        ITextEditor editor;
        try {
            editor = (ITextEditor) HandlerUtil.getActivePartChecked( event );
        } catch ( ExecutionException exc ) {
            throw new RuntimeException( exc );
        }

        ITextSelection sel = (ITextSelection) editor.getSelectionProvider().getSelection();

        // How to find out if sel is left-to-right or right-to-left?!

        editor.selectAndReveal( ... );

        return null;
    }
}

Update: There doesn't seem to be a way to do this without using the StyledText. I think this is weird and I considers placing a bug report suggesting that selection direction information should be added to ITextSelection. Before I do this it would be interesting to get the opinion on people here at SO about this proposal.

Upvotes: 1

Views: 1453

Answers (2)

willkil
willkil

Reputation: 1669

The best way to get the current cursor position is via ITextViewer.getTextWidget().getCaretOffset(). Here's an example that prints various text positions in an implementation of IContentAssistProcessor that I was working on:

public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
    int widgetCaretOffset = viewer.getTextWidget().getCaretOffset();
    if (viewer instanceof ITextViewerExtension5) {
        ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
        System.out.println(extension.widgetOffset2ModelOffset(widgetCaretOffset));
    }
    System.out.println(JFaceTextUtil.getOffsetForCursorLocation(viewer));
    System.out.println(offset);
    System.out.println(widgetCaretOffset);
    System.out.println(viewer.getSelectedRange());
}

I placed the caret at a random place in a document, then moved the mouse close to the beginning of the first line, then triggered the content assistant with various selections. In my case, the textViewer does not implement ITextViewerExtension5, so only four lines print. The output of the code above is below:

With nothing selected:

6
794
794
Point {794, 0}

With a left-to-right selection created by shift-right (caret blinking on right side of selection):

6
794
799
Point {794, 5}

Note that the caret position is 799, which equals 794 + 5.

With a left-to-right selection created by shift-left (caret blinking on left side of selection):

6
794
794
Point {794, 5}

Note that the caret position equals the selection offset.

Also note, although it's not relevant to this question, that the offset parameter in IContentAssistProcessor. computeCompletionProposals() is always the offset of the selection, not the caret.

If you have an ITextEditor instead of an ITextViewer, you can get the ITextViewer via the method from another answer to this question and from an answer to a different question:

ITextEditor editor;
ITextOperationTarget target = (ITextOperationTarget) editor.getAdapter(ITextOperationTarget.class);
if (target instanceof ITextViewer) {
    ITextViewer viewer = (ITextViewer) target;

    int widgetCaretOffset = viewer.getTextWidget().getCaretOffset();
    if (viewer instanceof ITextViewerExtension5) {
        ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
        System.out.println(extension.widgetOffset2ModelOffset(widgetCaretOffset));
    }
    System.out.println(JFaceTextUtil.getOffsetForCursorLocation(viewer));
    System.out.println(offset);
    System.out.println(widgetCaretOffset);
    System.out.println(viewer.getSelectedRange());
}

Upvotes: 2

Lii
Lii

Reputation: 12112

EDIT: This solution turned out to be wrong! Thanks to willkil for pointing it out.


This not very elegant piece of code was the most canonical way to achieve this I could find. It uses ITextEditor.getAdapter(ITextOperationTarget.class) and JFaceTextUtil. This implies that it depends on a particular editor implementation, but at least I don't have to touch it myself or mess with the widget2model methods.

public Object execute(ExecutionEvent event) {
    try {
        ITextViewer viewer = (ITextViewer)
            ((ITextEditor) HandlerUtil.getActivePartChecked(event))
                .getAdapter(ITextOperationTarget.class);
        int caretOffset = JFaceTextUtil.getOffsetForCursorLocation(viewer);
    } catch (ExecutionException exc) {
        throw new RuntimeException(exc);
    }
    return null;
}

Upvotes: 2

Related Questions