Reputation: 12112
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:
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.
Upvotes: 1
Views: 1453
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
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