/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package org.das2.jythoncompletion.support;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
/**
* Defines query processing of an asynchronous completion task.
*
* The {@link #query(CompletionResultSet, Document, int)} abstract method
* needs to be implemented to define the asynchronous querying behavior.
*
* In addition filtering of the result set computed during querying
* can be implemented by overriding the
* {@link #canFilter(JTextComponent)} and {@link #filter(CompletionResultSet)}.
*
* @author Miloslav Metelka, Dusan Balek
* @version 1.00
*/
public abstract class AsyncCompletionQuery {
private AsyncCompletionTask task;
/**
* Called in response to CompletionTask.refresh(null)
.
*
* The method gets invoked once the the user types a character
* but the CompletionTask.query()
was not yet invoked.
*
* The method may want to inspect the typed character before the caret
* position and decide whether the completion should be hidden
* if the typed character is inappropriate e.g. ";" for java completion.
*
* @since 1.3
*/
protected void preQueryUpdate(JTextComponent component) {
// Always done in AWT thread - by default do nothing
}
/**
* Perform the query and add results to the given result set.
*
* This method is always invoked asynchronously in a RequestProcessor
* thread.
*
* @param resultSet result set into which the computed data should be added.
* The result set must always be finished
* by {@link org.netbeans.spi.editor.completion.CompletionResultSet#finish()}.
*
* @param doc document of the text component on which the query is being run.
*
* Can be null
if the corresponding component is null.
*
* @param caretOffset present caret offset of the text component
* on which the query is being run.
*
* Can be -1
if the corresponding component is null.
*/
protected abstract void query(CompletionResultSet resultSet, Document doc, int caretOffset);
/**
* Check whether the query results can successfully be filtered.
*
* This method is invoked synchronously in response to call
* of {@link org.netbeans.spi.editor.completion.CompletionTask#refresh(CompletionResultSet)}
* in AWT thread. The asynchronous query method
* {@link #query(CompletionResultSet, Document, int)}
* may still be running when this method is invoked.
*
*
* The implementation typically gets the text between
* caret offset remembered during query and the present caret offset
* (can be gathered by component.getCaretPosition()
)
* and examines whether the results computed (or being computed) during the query
* (they should be collected and rememberred in the query method body)
* can be filtered appropriately.
*
* For example in java the user can type e.g. "my" and so all the classes
* and fields and methods starting with "my" appropriate for the given context
* will be computed during the query.
*
* If the user continues typing e.g. "myMethod" then the result set
* computed during the query can be filtered and this method should return true.
*
* However if the user has typed e.g. "my()." then the original result
* set is useless and this method should return false.
*
* @param component text component for which this provider was constructed.
* It may be null if no text component was provided.
*
* @return true if the filtering can be done according to the current conditions
* (such as caret offset).
*
* Return false
if the filtering cannot be done or is not supported
* at all by this query implementation. The full asynchronous query
* will be invoked then.
*
* If there is a query still in progress this method should check
* whether the results that the query is computing would be usable
* for the present coditions and if not it should tell the query
* to stop (e.g. through a boolean flag that the query checks).
*
* Anyway if there is a query still in progress this method
* will be re-called again once the query finishes.
*
* The default implementation just returns false.
*/
protected boolean canFilter(JTextComponent component) {
return false;
}
/**
* Filter the data collected during the last
* {@link #query(CompletionResultSet, Document, int)} invocation.
*
* This method is called in response
* to {@link org.netbeans.spi.editor.completion.CompletionTask#refresh(CompletionResultSet)} call.
*
* This method is always invoked in AWT thread and it is supposed
* to finish quickly. It will only be invoked when a preceding
* synchronous invocation
* of {@link #canFilter(JTextComponent)} returned true
* and when there is currently no query in progress
* so it is safe to use the results computed during the query.
*
*
* The implementation typically gets the text between
* caret offset remembered during query and the present caret offset
* (can be gathered by component.getCaretPosition()
)
* and examines whether the results computed during the query
* (they should be rememberred in the query method body)
* can be filtered appropriately.
*
* For example in java the user can type e.g. "my" and so all the classes
* and fields and methods starting with "my" appropriate for the given context
* will be computed during the query.
*
* If the user continues typing e.g. "myMethod" then the result set
* computed during the query can be filtered and this method should return true.
*
* However if the user has typed e.g. "my()." then the original result
* set is useless and this method should return false.
*
*
* The default implementation does not support filtering
* and throws IllegalStateException
.
*
* @param resultSet result set to which the filtering must add
* its results. The result set must always be finished
* by {@link org.netbeans.spi.editor.completion.CompletionResultSet#finish()}.
*/
protected void filter(CompletionResultSet resultSet) {
throw new IllegalStateException("Filtering not supported"); // NOI18N
}
/**
* Collect additional information in AWT thread before
* {@link #query(CompletionResultSet, Document, int)}
* is called asynchronously.
*
* @param component text component for which this provider was constructed.
* It may be null if no text component was provided.
*/
protected void prepareQuery(JTextComponent component) {
// Always done in AWT thread - by default do nothing
}
/**
* Check whether the task corresponding to this query was cancelled.
*
* Subclasses should check this flag and stop the query computation.
*
* @return true if the task was cancelled or false if not.
*/
public final boolean isTaskCancelled() {
assert (task != null) : "isTaskCancelled() must not be called from constructor"; // NOI18N
return task.isCancelled();
}
final void initTask(AsyncCompletionTask task) {
assert (task != null); // assign non-null task
assert (this.task == null); // not assigned yet
this.task = task;
}
}