【问题标题】:Caret position of Eclipse text editorEclipse 文本编辑器的插入符号位置
【发布时间】:2019-08-20 15:21:02
【问题描述】:

我正在编写一个小插件来将 Eclipse 文本编辑器的插入符号位置移动到选定块的另一侧。问题是我找不到一个很好的方法来发现选择是从左到右还是从右到左。

我知道有以下选择:

  • 以某种方式使用 CarretListener。这似乎没有必要,我不想这样做。
  • 抓住底层StyledText 并将选择与插入符号位置进行比较。似乎打破了抽象,因为我必须知道编辑器是如何实现的。另一个缺点是您必须在文本查看器上使用widgetOffset2ModelOffset 方法来调整位置。

我不能从我的ITextEditorISelectionProvider 或其他东西中获得插入符号的位置吗?

这是我的代码:

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;
    }
}

更新:如果不使用StyledText,似乎没有办法做到这一点。我认为这很奇怪,我考虑放置一个错误报告,建议应将选择方向信息添加到ITextSelection。在我这样做之前,我会很有趣地了解 SO 这里的人们对这个提议的看法。

【问题讨论】:

    标签: eclipse eclipse-plugin


    【解决方案1】:

    编辑:这个解决方案被证明是错误的!感谢 willkil 指出。


    这段不太优雅的代码是我能找到的最规范的实现方式。它使用ITextEditor.getAdapter(ITextOperationTarget.class)JFaceTextUtil。这意味着它依赖于特定的编辑器实现,但至少我不必自己动手或弄乱widget2model 方法。

    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;
    }
    

    【讨论】:

    • JFaceTextUtil.getOffsetForCursorLocation() 给出了 mouse cursor 的文本偏移量,而不是插入符号。
    • @willkil:嗯,是这样吗?我几乎可以肯定它在某些时候适用于键盘光标......但我也看到很久以前我已经从我的代码中删除了这个方法的使用,并带有注释// This returns the wrong offset sometimes. Started with Kepler. Hm。当我有更多时间时,我将不得不对此进行调查。感谢您指出!
    • 一开始我也认为它也有效,但结果我在文档中单击该位置后自然将鼠标光标留在了选择附近。
    【解决方案2】:

    获取当前光标位置的最佳方法是通过ITextViewer.getTextWidget().getCaretOffset()。这是一个在我正在处理的IContentAssistProcessor 实现中打印各种文本位置的示例:

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

    我将插入符号放在文档中的任意位置,然后将鼠标移动到靠近第一行的开头,然后通过各种选择触发内容助手。在我的例子中,textViewer 没有实现 ITextViewerExtension5,所以只打印了四行。上面代码的输出如下:

    没有选择任何内容:

    6
    794
    794
    Point {794, 0}
    

    通过右移创建从左到右的选择(插入符号在选择的右侧闪烁):

    6
    794
    799
    Point {794, 5}
    

    注意插入符号的位置是 799,等于 794 + 5。

    通过左移创建从左到右的选择(选择左侧的插入符号闪烁):

    6
    794
    794
    Point {794, 5}
    

    请注意,插入符号的位置等于选择偏移量。

    另请注意,尽管与此问题无关,IContentAssistProcessor. computeCompletionProposals() 中的 offset 参数始终是选择的偏移量,而不是插入符号。

    如果您有ITextEditor 而不是ITextViewer,您可以通过another answer 到这个问题和an answera different question 的方法获得ITextViewer

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

    【讨论】:

    • ITextViewer.getTextWidget 也是我最后在我的代码中使用的。感谢您发布问题的准确答案!
    • 如果您的代码要在任意文本编辑器上运行,我认为您还应该在从getTextWidget 得到的偏移量上调用JFaceTextUtil.widgetLine2ModelLine。至少如果您使用带有IDocument 的偏移量。
    • @Lii 看来您对widgtLine2ModelLine() 的看法是正确的。谢谢。我会编辑我的答案。当我对此进行测试时,文档开始始终位于可见区域中。我也没有检查偏移量是否完全正确,只是它是一致且合理的。我会仔细检查。
    • @Lii 我找到了一些时间来检查这个。调用widgtLine2ModelLine() 是不正确的。 StyledText.getCaretOffset() 根据its javadoc 返回“相对于文本开头的插入符号位置 [强调添加]”。我的测试证实我总是得到正确的结果,即使文本被滚动。这是有道理的,考虑到项目被称为插入符号 offset,而不是插入符号 line
    • 我还没有真正理解小部件和模型线和偏移量的东西。在我上面的评论中,我弄错了使用哪些方法,但我认为你应该使用widgetOffset2ModelOffset,就像他们使用here一样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-24
    • 2014-03-10
    • 1970-01-01
    相关资源
    最近更新 更多