1 19 20 package org.netbeans.modules.editor.html; 21 22 import java.util.List ; 23 import javax.swing.text.Document ; 24 import javax.swing.text.JTextComponent ; 25 import org.netbeans.api.editor.completion.Completion; 26 import org.netbeans.api.html.lexer.HTMLTokenId; 27 import org.netbeans.api.lexer.Token; 28 import org.netbeans.api.lexer.TokenHierarchy; 29 import org.netbeans.api.lexer.TokenSequence; 30 import org.netbeans.editor.BaseDocument; 31 import org.netbeans.editor.Utilities; 32 import org.netbeans.editor.ext.CompletionQuery; 33 import org.netbeans.editor.ext.CompletionQuery.ResultItem; 34 import org.netbeans.editor.ext.ExtSyntaxSupport; 35 import org.netbeans.editor.ext.html.HTMLCompletionQuery; 36 import org.netbeans.editor.ext.html.HTMLCompletionQuery.HTMLResultItem; 37 import org.netbeans.editor.ext.html.HTMLSyntaxSupport; 38 import org.netbeans.spi.editor.completion.CompletionResultSet; 39 import org.netbeans.spi.editor.completion.CompletionProvider; 40 import org.netbeans.spi.editor.completion.CompletionTask; 41 import org.netbeans.spi.editor.completion.support.AsyncCompletionQuery; 42 import org.netbeans.spi.editor.completion.support.AsyncCompletionTask; 43 44 45 50 public class HTMLCompletionProvider implements CompletionProvider { 51 52 53 public HTMLCompletionProvider() { 54 } 55 56 public int getAutoQueryTypes(JTextComponent component, String typedText) { 57 int type = ((HTMLSyntaxSupport)Utilities.getDocument(component).getSyntaxSupport()).checkCompletion(component, typedText, false); 58 return type == ExtSyntaxSupport.COMPLETION_POPUP ? COMPLETION_QUERY_TYPE + DOCUMENTATION_QUERY_TYPE : 0; 59 } 60 61 public CompletionTask createTask(int queryType, JTextComponent component) { 62 AsyncCompletionTask task = null; 63 if ((queryType & COMPLETION_QUERY_TYPE & COMPLETION_ALL_QUERY_TYPE) != 0) { 64 task = new AsyncCompletionTask(new Query(), component); 65 } else if (queryType == DOCUMENTATION_QUERY_TYPE) { 66 task = new AsyncCompletionTask(new DocQuery(null), component); 67 } 68 return task; 69 } 70 71 static class Query extends AbstractQuery { 72 73 private JTextComponent component; 74 75 protected void prepareQuery(JTextComponent component) { 76 this.component = component; 77 } 78 79 protected void doQuery(CompletionResultSet resultSet, Document doc, int caretOffset) { 80 HTMLCompletionQuery.HTMLCompletionResult res = (HTMLCompletionQuery.HTMLCompletionResult)queryImpl(component, caretOffset); 81 if(res == null) { 82 return ; 83 } 84 85 List results = res.getData(); 86 assert (results != null); 87 resultSet.addAllItems(results); 88 resultSet.setTitle(res.getTitle()); 89 resultSet.setAnchorOffset(res.getSubstituteOffset()); 90 } 91 } 92 93 static class DocQuery extends AbstractQuery { 94 95 private JTextComponent component; 96 private ResultItem item; 97 98 DocQuery(HTMLResultItem item) { 99 this.item = item; 100 } 101 102 protected void prepareQuery(JTextComponent component) { 103 this.component = component; 104 } 105 106 protected void doQuery(CompletionResultSet resultSet, Document doc, int caretOffset) { 107 CompletionQuery.Result res = null; 108 if(item == null) { 109 res = queryImpl(component, caretOffset); 110 if(res != null) { 111 List result = res.getData(); 112 if(result != null && result.size() > 0) { 113 Object resultObj = result.get(0); 114 if(resultObj instanceof ResultItem) 115 item = (ResultItem)resultObj; 116 } 117 } 118 } 119 HTMLResultItem htmlItem = (HTMLResultItem)item; 120 if(htmlItem != null && htmlItem.getHelpID() != null) { 121 resultSet.setDocumentation(new HTMLCompletionQuery.DocItem(htmlItem)); 122 if(res != null) { 123 resultSet.setTitle(res.getTitle()); 124 resultSet.setAnchorOffset(((HTMLCompletionQuery.HTMLCompletionResult)res).getSubstituteOffset()); 125 } 126 } 127 } 128 } 129 130 private static CompletionQuery.Result queryImpl(JTextComponent component, int offset) { 131 Class kitClass = Utilities.getKitClass(component); 132 if (kitClass != null) { 133 HTMLSyntaxSupport support = (HTMLSyntaxSupport)Utilities.getSyntaxSupport(component); 134 return HTMLCompletionQuery.getDefault().query(component, offset, support); 135 } else { 136 return null; 137 } 138 } 139 140 private static abstract class AbstractQuery extends AsyncCompletionQuery { 141 142 protected void preQueryUpdate(JTextComponent component) { 143 int caretOffset = component.getCaretPosition(); 144 Document doc = component.getDocument(); 145 checkHideCompletion((BaseDocument)doc, caretOffset); 146 } 147 148 protected void query(CompletionResultSet resultSet, Document doc, int caretOffset) { 149 checkHideCompletion((BaseDocument)doc, caretOffset); 150 doQuery(resultSet, doc, caretOffset); 151 resultSet.finish(); 152 } 153 154 abstract void doQuery(CompletionResultSet resultSet, Document doc, int caretOffset); 155 156 } 157 158 private static void checkHideCompletion(BaseDocument doc, int caretOffset) { 159 doc.readLock(); 164 try { 165 TokenHierarchy tokenHierarchy = TokenHierarchy.get(doc); 166 TokenSequence tokenSequence = tokenHierarchy.tokenSequence(); 167 168 tokenSequence.move(caretOffset == 0 ? 0 : caretOffset - 1); 169 if (!tokenSequence.moveNext()) 170 return; 171 172 Token tokenItem = tokenSequence.token(); 173 if(tokenItem.id() == HTMLTokenId.TEXT && !tokenItem.text().toString().startsWith("<") && !tokenItem.text().toString().startsWith("&")) { 174 hideCompletion(); 175 } 176 177 }finally { 178 doc.readUnlock(); 179 } 180 } 181 182 private static void hideCompletion() { 183 Completion.get().hideCompletion(); 184 Completion.get().hideDocumentation(); 185 } 186 } 187 | Popular Tags |