Search code examples
eclipseeclipse-plugin

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:

  • Use a CarretListener in some way. It seems unnecessary and I don't want to.
  • Get hold of the underlaying StyledText and compare selection with the caret position. Seems to break abstraction because I have to know how the editor is implemented. Another disadvantage is that you would have to use widgetOffset2ModelOffset methods on the text viewer to adjust positions.

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.


Solution

  • 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());
    }