在Eclipse SWT / JFace中具有自动完成功能的TextCellEditor?

时间:2017-12-10 20:48:51

标签: eclipse textbox swt jface

我想要一个具有标准自动完成行为的TextCellEditor,这是当前任何用户在输入单元格中键入建议字符串列表时所期望的。关于我所追求的一个很好的工作示例,在Javascript中,请参阅此jQuery autocomplete widget

我找不到一个好例子。 我只发现了(除了一些微小的变化)TextCellEditorWithContentProposal snippet。但这还有很多不足之处:

  • 它列出了所有单词,无论单元格中输入的“部分单词”(没有部分匹配)
  • 当选择了所需的单词时,它会附加到部分单词,而不是替换它
  • 交互是丑陋且不直观的。例如,人们会期待 逃离密钥以撕下建议清单;再次,请参阅Javascript示例;在这里,它还删除了键入的字母。

我觉得这样一个标准且有用的组件是不可用的。或者也许它可用?有人能指出我更合适的片段或例子吗?

2 个答案:

答案 0 :(得分:3)

您要链接的示例是一个代码段,旨在展示API并指导您根据自己的喜好自定义控件。

您的某些投诉无效或可以使用公共API轻松修复。

让我们详细介绍一下。

列出所有提案,不论输入的文字

请注意,在代码段中使用了org.eclipse.jface.fieldassist.SimpleContentProposalProvider

IContentProposalProvider contentProposalProvider = new SimpleContentProposalProvider(new String[] { "red",
                    "green", "blue" });
cellEditor = new TextCellEditorWithContentProposal(viewer.getTable(), contentProposalProvider, null, null);

正如其javadoc中所建议的那样:

  

旨在将字符串的静态列表映射到内容提案

要启用对代码段内容的简单过滤,您可以致电:contentProposalProvider.setFiltering(true);

对于任何更复杂的内容,您必须将其替换为您自己的org.eclipse.jface.fieldassist.IContentProposalProvider实现。

选择附加到单元格内容,而不是替换它

内容提案行为在org.eclipse.jface.fieldassist.ContentProposalAdapter中定义。再次,对org.eclipse.jface.fieldassist.ContentProposalAdapter.setProposalAcceptanceStyle(int)的简单方法调用将实现您的目标行为:

contentProposalAdapter = new ContentProposalAdapter(text, new TextContentAdapter(), contentProposalProvider, keyStroke, autoActivationCharacters);
contentProposalAdapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE);

取消提案不应删除已键入的内容

仅仅使用API​​很难做到,因为ContentProposalAdapter只会将关键笔划传播到打开的ContentProposalPopup而不存储它们。

您必须继承ContentProposalAdapter,才能访问ContentProposalAdapter.ContentProposalPopup.filterText

此片段中包含合理默认值的大多数功能也可以通过org.eclipse.jface.fieldassist.AutoCompleteField以更简单的方式获得。

答案 1 :(得分:0)

以下是向您展示一个简单实现的代码段。您必须对其进行自定义,但它可以为您提供方法。

注意,这不是文档的一般副本/粘贴内容,也不是有关文档的说明。

String[] contentProposals = {"text", "test", "generated"};
// simple content provider based on string array
SimpleContentProposalProvider provider = new SimpleContentProposalProvider(contentProposals);
// enable filtering or disabled it if you are using your own implementation
provider.setFiltering(false);
// content adapter with no keywords and caracters filtering
ContentProposalAdapter adapter = new ContentProposalAdapter(yourcontrolswt, new TextContentAdapter(), provider, null, null);
// you should not replace text content, you will to it bellow
adapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_IGNORE);
// now just put your implementation
adapter.addContentProposalListener(new IContentProposalListener() {

        @Override
         public void proposalAccepted(IContentProposal proposal) {
                if(proposal != null && StringUtils.isNotBlank(proposal.getContent())){
                       // you need filter with blank spaces
                        String contentTextField = getFilterControl().getText();
                         String[] currentWords = getFilterControl().getText().split(" ");
                         StringBuilder textToDisplay = new StringBuilder();
                         if(currentWords.length > 1) {
                                // delete and replace last word
                                String lastWord = currentWords[currentWords.length-1];
                                textToDisplay.append(contentTextField.substring(0, contentTextField.length()-1-lastWord.length()));
                                textToDisplay.append(" ");
                         }
                       // add current proposal to control text content
                       textToDisplay.append(proposal.getContent());
                       yourcontrolswt.setText(textToDisplay.toString());
                }
         }
    });

如果需要更多内容,还可以拥有自己的内容提议提供者。如果需要特定的对象而不是字符串或类似的东西。

 public class SubstringMatchContentProposalProvider implements IContentProposalProvider {

    private List<String> proposals = Collections.emptyList();

    @Override
    public IContentProposal[] getProposals(String contents, int position) {
        if (position == 0) {
            return null;

        }
        String[] allWords = contents.split(" ");
        // no words available
        if(allWords.length == 0 || StringUtils.isBlank(allWords[allWords.length-1]))
        return null;

        // auto completion on last word found
        String lastWordFound = allWords[allWords.length-1];
        Pattern pattern = Pattern.compile(lastWordFound,
                Pattern.LITERAL | Pattern.CASE_INSENSITIVE /*| Pattern.UNICODE_CASE*/); // this should be not used for better performances
        IContentProposal[] filteredProposals = proposals.stream()
                .filter(proposal -> proposal.length() >= lastWordFound.length() && pattern.matcher(proposal).find())
                .map(ContentProposal::new).toArray(IContentProposal[]::new);

        // no result
        return filteredProposals.length == 0 ? null : filteredProposals;

    }

    public void setProposals(List<String> proposals) {
        this.proposals = proposals;
    }

}