001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.editor.java;
043:
044: import com.sun.source.tree.Scope;
045: import java.awt.Color;
046: import java.awt.Font;
047: import java.awt.Graphics;
048: import java.awt.event.KeyEvent;
049: import java.util.EnumSet;
050: import javax.lang.model.element.Element;
051: import javax.lang.model.element.ElementKind;
052: import javax.lang.model.element.TypeElement;
053: import javax.lang.model.type.DeclaredType;
054: import javax.lang.model.util.Elements;
055: import javax.swing.text.JTextComponent;
056: import org.netbeans.api.java.source.CompilationController;
057: import org.netbeans.api.java.source.Task;
058: import org.netbeans.api.java.source.ElementHandle;
059: import org.netbeans.api.java.source.JavaSource;
060: import org.netbeans.spi.editor.completion.CompletionTask;
061: import org.netbeans.spi.editor.completion.LazyCompletionItem;
062: import org.netbeans.spi.editor.completion.support.CompletionUtilities;
063:
064: /**
065: *
066: * @author Dusan Balek
067: */
068: public class LazyTypeCompletionItem extends JavaCompletionItem
069: implements LazyCompletionItem {
070:
071: public static final LazyTypeCompletionItem create(
072: ElementHandle<TypeElement> handle,
073: EnumSet<ElementKind> kinds, int substitutionOffset,
074: JavaSource javaSource, boolean insideNew) {
075: return new LazyTypeCompletionItem(handle, kinds,
076: substitutionOffset, javaSource, insideNew);
077: }
078:
079: private ElementHandle<TypeElement> handle;
080: private EnumSet<ElementKind> kinds;
081: private JavaSource javaSource;
082: private boolean insideNew;
083: private String name;
084: private String simpleName;
085: private String pkgName;
086: private JavaCompletionItem delegate = null;
087: private CharSequence sortText;
088: private int prefWidth = -1;
089:
090: private LazyTypeCompletionItem(ElementHandle<TypeElement> handle,
091: EnumSet<ElementKind> kinds, int substitutionOffset,
092: JavaSource javaSource, boolean insideNew) {
093: super (substitutionOffset);
094: this .handle = handle;
095: this .kinds = kinds;
096: this .javaSource = javaSource;
097: this .insideNew = insideNew;
098: this .name = handle.getQualifiedName();
099: int idx = name.lastIndexOf('.'); //NOI18N
100: this .simpleName = idx > -1 ? name.substring(idx + 1) : name;
101: this .pkgName = idx > -1 ? name.substring(0, idx) : ""; //NOI18N
102: this .sortText = this .simpleName
103: + Utilities.getImportanceLevel(this .pkgName) + "#"
104: + this .pkgName; //NOI18N
105: }
106:
107: public boolean accept() {
108: if (handle != null) {
109: if (isAnnonInner()) {
110: handle = null;
111: return false;
112: }
113: try {
114: long t = System.currentTimeMillis();
115: javaSource.runUserActionTask(
116: new Task<CompilationController>() {
117:
118: public void run(
119: CompilationController controller)
120: throws Exception {
121: controller
122: .toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
123: Scope scope = controller
124: .getTrees()
125: .getScope(
126: controller
127: .getTreeUtilities()
128: .pathFor(
129: substitutionOffset));
130: if (!isAnnonInner()) {
131: TypeElement e = handle
132: .resolve(controller);
133: Elements elements = controller
134: .getElements();
135: if (e != null
136: && (Utilities
137: .isShowDeprecatedMembers() || !elements
138: .isDeprecated(e))
139: && controller.getTrees()
140: .isAccessible(
141: scope, e)) {
142: if (isOfKind(e, kinds))
143: delegate = JavaCompletionItem
144: .createTypeItem(
145: e,
146: (DeclaredType) e
147: .asType(),
148: substitutionOffset,
149: true,
150: controller
151: .getElements()
152: .isDeprecated(
153: e),
154: insideNew,
155: false);
156: }
157: }
158: handle = null;
159: }
160: }, true);
161: } catch (Throwable t) {
162: }
163: }
164: return delegate != null;
165: }
166:
167: public void defaultAction(JTextComponent component) {
168: if (delegate != null)
169: delegate.defaultAction(component);
170: }
171:
172: public void processKeyEvent(KeyEvent evt) {
173: if (delegate != null)
174: delegate.processKeyEvent(evt);
175: }
176:
177: public int getPreferredWidth(Graphics g, Font defaultFont) {
178: if (prefWidth < 0)
179: prefWidth = CompletionUtilities.getPreferredWidth(
180: simpleName + " (" + pkgName + ")", null, g,
181: defaultFont); //NOI18N
182: return prefWidth;
183: }
184:
185: public void render(Graphics g, Font defaultFont,
186: Color defaultColor, Color backgroundColor, int width,
187: int height, boolean selected) {
188: if (delegate != null)
189: delegate.render(g, defaultFont, defaultColor,
190: backgroundColor, width, height, selected);
191: }
192:
193: public CompletionTask createDocumentationTask() {
194: if (delegate != null)
195: return delegate.createDocumentationTask();
196: return null;
197: }
198:
199: public CompletionTask createToolTipTask() {
200: if (delegate != null)
201: return delegate.createToolTipTask();
202: return null;
203: }
204:
205: public int getSortPriority() {
206: return 700;
207: }
208:
209: public CharSequence getSortText() {
210: return sortText;
211: }
212:
213: public CharSequence getInsertPrefix() {
214: return simpleName;
215: }
216:
217: boolean isAnnonInner() {
218: return simpleName.length() == 0
219: || Character.isDigit(simpleName.charAt(0));
220: }
221:
222: private boolean isOfKind(Element e, EnumSet<ElementKind> kinds) {
223: if (kinds.contains(e.getKind()))
224: return true;
225: for (Element ee : e.getEnclosedElements())
226: if (isOfKind(ee, kinds))
227: return true;
228: return false;
229: }
230: }
|