1 package com
.intellij
.ui
;
3 import com
.intellij
.codeInsight
.lookup
.LookupArranger
;
4 import com
.intellij
.codeInsight
.lookup
.LookupElement
;
5 import com
.intellij
.codeInsight
.lookup
.LookupElementBuilder
;
6 import com
.intellij
.codeInsight
.lookup
.LookupManager
;
7 import com
.intellij
.codeInsight
.lookup
.impl
.LookupImpl
;
8 import com
.intellij
.lang
.Language
;
9 import com
.intellij
.openapi
.actionSystem
.ActionManager
;
10 import com
.intellij
.openapi
.actionSystem
.AnAction
;
11 import com
.intellij
.openapi
.actionSystem
.AnActionEvent
;
12 import com
.intellij
.openapi
.actionSystem
.IdeActions
;
13 import com
.intellij
.openapi
.editor
.Document
;
14 import com
.intellij
.openapi
.editor
.Editor
;
15 import com
.intellij
.openapi
.editor
.EditorFactory
;
16 import com
.intellij
.openapi
.fileTypes
.FileType
;
17 import com
.intellij
.openapi
.fileTypes
.PlainTextLanguage
;
18 import com
.intellij
.openapi
.project
.Project
;
19 import com
.intellij
.openapi
.util
.text
.StringUtil
;
20 import com
.intellij
.psi
.PsiDocumentManager
;
21 import com
.intellij
.psi
.PsiFile
;
22 import com
.intellij
.psi
.PsiFileFactory
;
23 import com
.intellij
.psi
.codeStyle
.NameUtil
;
24 import com
.intellij
.util
.Function
;
25 import com
.intellij
.util
.LocalTimeCounter
;
26 import com
.intellij
.util
.containers
.ContainerUtil
;
27 import org
.jetbrains
.annotations
.Nullable
;
29 import java
.util
.ArrayList
;
30 import java
.util
.Collections
;
31 import java
.util
.Comparator
;
32 import java
.util
.List
;
35 * @author Roman Chernyatchik
37 * It is text field with autocompletion from list of values.
39 * Autocompletion is implemented via LookupManager.
40 * Use setVariants(..) set list of values for autocompletion.
41 * For variants you can use not only instances of PresentableLookupValue, but
42 * also instances of LookupValueWithPriority and LookupValueWithUIHint
44 public class TextFieldWithAutoCompletion
extends EditorTextField
{
45 private List
<LookupElement
> myVariants
;
46 private String myAdText
;
48 public TextFieldWithAutoCompletion() {
52 public TextFieldWithAutoCompletion(final Project project
) {
53 super(createDocument(project
), project
, PlainTextLanguage
.INSTANCE
.getAssociatedFileType());
55 new VariantsCompletionAction();
58 private static Document
createDocument(@Nullable final Project project
) {
59 if (project
== null) {
60 return EditorFactory
.getInstance().createDocument("");
63 final Language language
= PlainTextLanguage
.INSTANCE
;
64 final PsiFileFactory factory
= PsiFileFactory
.getInstance(project
);
65 final FileType fileType
= language
.getAssociatedFileType();
66 assert fileType
!= null;
68 final long stamp
= LocalTimeCounter
.currentTime();
69 final PsiFile psiFile
= factory
.createFileFromText("Dummy." + fileType
.getDefaultExtension(), fileType
, "", stamp
, true, false);
70 final Document document
= PsiDocumentManager
.getInstance(project
).getDocument(psiFile
);
71 assert document
!= null;
75 private class VariantsCompletionAction
extends AnAction
{
76 private VariantsCompletionAction() {
77 final AnAction action
= ActionManager
.getInstance().getAction(IdeActions
.ACTION_CODE_COMPLETION
);
79 registerCustomShortcutSet(action
.getShortcutSet(), TextFieldWithAutoCompletion
.this);
83 public void actionPerformed(final AnActionEvent e
) {
84 final Editor editor
= getEditor();
85 assert editor
!= null;
87 editor
.getSelectionModel().removeSelection();
88 final String lookupPrefix
= getCurrentLookupPrefix(getCurrentTextPrefix());
89 final LookupImpl lookup
=
90 (LookupImpl
)LookupManager
.getInstance(getProject()).createLookup(editor
,
91 calcLookupItems(lookupPrefix
),
92 lookupPrefix
!= null ? lookupPrefix
: "",
93 LookupArranger
.DEFAULT
);
94 final String advertisementText
= getAdvertisementText();
95 if (!StringUtil
.isEmpty(advertisementText
)) {
96 lookup
.setAdvertisementText(advertisementText
);
103 public void setAdvertisementText(@Nullable String text
) {
107 public String
getAdvertisementText() {
111 public void setVariants(@Nullable final List
<LookupElement
> variants
) {
112 myVariants
= (variants
!= null) ? variants
: Collections
.<LookupElement
>emptyList();
115 public void setVariants(@Nullable final String
[] variants
) {
116 myVariants
= (variants
== null)
117 ? Collections
.<LookupElement
>emptyList()
118 : ContainerUtil
.map(variants
, new Function
<String
, LookupElement
>() {
119 public LookupElement
fun(final String s
) {
120 return LookupElementBuilder
.create(s
);
125 private LookupElement
[] calcLookupItems(@Nullable final String lookupPrefix
) {
126 if (lookupPrefix
== null) {
127 return new LookupElement
[0];
130 final List
<LookupElement
> items
= new ArrayList
<LookupElement
>();
131 if (lookupPrefix
.length() == 0) {
132 items
.addAll(myVariants
);
134 final NameUtil
.Matcher matcher
= NameUtil
.buildMatcher(lookupPrefix
, 0, true, true);
136 for (LookupElement variant
: myVariants
) {
137 if (matcher
.matches(variant
.getLookupString())) {
143 Collections
.sort(items
, new Comparator
<LookupElement
>() {
144 public int compare(final LookupElement item1
,
145 final LookupElement item2
) {
146 return item1
.getLookupString().compareTo(item2
.getLookupString());
150 return items
.toArray(new LookupElement
[items
.size()]);
154 * Returns prefix for autocompletion and lookup items matching.
157 protected String
getCurrentLookupPrefix(final String currentTextPrefix
) {
158 return currentTextPrefix
;
161 private String
getCurrentTextPrefix() {
162 return getText().substring(0, getCaretModel().getOffset());