All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.editor.ext.CompletionQuery Maven / Gradle / Ivy

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.editor.ext;

import java.util.List;
import java.util.Iterator;
import java.awt.Color;
import java.awt.Component;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.BadLocationException;
import org.netbeans.editor.SyntaxSupport;
import org.netbeans.editor.BaseDocument;

/**
* Code completion querying SPI and support.
*
* @author Miloslav Metelka
* @version 1.01
*/

public interface CompletionQuery {

    /** Perform the query on the given component. The query usually
    * gets the component's document, the caret position and searches back
    * to find the last command start. Then it inspects the text up to the caret
    * position and returns the result.
    * 

Implementations must be thread safe (also reentrant) because it can be * called speculatively from multiple threads. This requirement can be removed in future SPI * by passing additional flag marking speculative query. Skeletal implementation * could handle multithreading based on the flag. * @param component the component to use in this query. * @param offset position in the component's document to which the query will * be performed. Usually it's a caret position. * @param support syntax-support that will be used during resolving of the query. * @return result of the query or null if there's no result. */ public Result query(JTextComponent component, int offset, SyntaxSupport support); /** * Marker interface that should implement all providers that are * compatible with #13768 semantics. It requires thread safe and reentrant * completion query provider implementation. It's performance gain * to implement as it allows asynchronous speculative queries. * * @deprecated It is a workaround. It's suggested that providers * should wait for new completion query SPI that should better * support speculative queries, partial results, result * cancellation and result narrowing. Implement only if it's simple. * * @since CompletionQuery version 1.01 */ public interface SupportsSpeculativeInvocation { // marker interface } /** Result of the query or expression evaluation. Simply said it consists * of the list of the data and title and an internal information about * how to substitute the text. */ public interface Result { /** Get the list with the items satisfying the query. The list * must always be non-null. If there are no data it will have a zero size. * @return List of objects implementing ResultItem. */ public List getData(); /** Get the title describing the result or null if there's no title. */ public String getTitle(); /** Substitute the text in the document if the user picks * the item from the data with the given index either by * pressing ENTER or doubleclicking the item by mouse. * @param dataIndex current selected item index in the current data list. * It can be used for making the substitution. * @param shift indicates request for some kind of different behaviour, * means that e.g. user hold shift while pressing ENTER. * @return whether the text was substituted or not */ public boolean substituteText(int dataIndex, boolean shift); /** Substitute the text that is common for all the data entries. * This is used to update the document with * the common text when the user presses the TAB key. * @param dataIndex current selected item index in the current data list. * Although normally it shouldn't be necessary for making * the substitution, the completion implementations * can use it for customized behavior. * @return whether the text was substituted or not */ public boolean substituteCommonText(int dataIndex); } /** * The very basic funztionality of Result is implemented by this class, * but parts general enough to not need to be overriden. */ public static abstract class AbstractResult implements Result { /** The List of the ResultItem instances - the content of the result */ private List data; /** The title of the result */ private String title; public AbstractResult(List data, String title) { this.data = data; this.title = title; } public List getData() { return data; } public String getTitle() { return title; } } /** Full implementation of Result, managing substitution of the text and * finding and substituting common prefix of items */ public static class DefaultResult extends AbstractResult { private JTextComponent component; private int offset; private int len; /** Constructor for DefaultResult * @param component the JTextComponent the result is tightened with, * used for operations on its Document, caret, selection and so. * @param title the title displayed in header of completion window * @param data the list of ResultItem instances to be displayed in * completion window, may be null. * @param the offset in the document corresponding to the start * of the text occassionally replaced by the result. * @param the length of the text to be replaced. */ public DefaultResult(JTextComponent component, String title, List data, int offset, int len ) { super(data, title); this.component = component; this.offset = offset; this.len = len; } /** Internal method used to find longest common prefix of two Strings. * it is made private, because I'm going to change its interface * for better performance. */ private int getCommonPrefixLength( char[] commonPrefix, int len, String s ) { char[] c = s.toCharArray(); int i=0; if( len > c.length ) len = c.length; for( ; ithis. * @param JList the list this item will be drawn into, usefull e.g. for * obtaining preferred colors. * @param isSelected tells if this item is just selected, for using * proper color scheme. * @param cellHasFocus tells it this item is just focused. * @return the component usable for painting this value */ public Component getPaintComponent( JList list, boolean isSelected, boolean cellHasFocus); } /** A class providing generic, nearly full implementation of ResultItem */ public abstract static class AbstractResultItem implements CompletionQuery.ResultItem { /* The text this item would expand to */ protected String text; /** Create new ResultItem for given text, should be used in subclass constructors */ public AbstractResultItem( String text ) { this.text = text; } /** Generic implementation, behaves just as described in specification * in substituteCommonText() - removes len * characters at offset out of document and then inserts * subLen characters from the text */ public boolean substituteCommonText( JTextComponent c, int offset, int len, int subLen ) { BaseDocument doc = (BaseDocument)c.getDocument(); try { doc.atomicLock(); try { doc.remove( offset, len ); doc.insertString( offset, text.substring( 0, subLen ), null); } finally { doc.atomicUnlock(); } } catch( BadLocationException exc ) { return false; //not sucessfull } return true; } /** Generic implementation, behaves just as described in specification * in substituteText() - removes len characters * at offset out of document and then inserts * whole text. Ignores shift argument. */ public boolean substituteText( JTextComponent c, int offset, int len, boolean shift ) { BaseDocument doc = (BaseDocument)c.getDocument(); try { doc.atomicLock(); try { String textToReplace = doc.getText(offset, len); if (text.equals(textToReplace)) return false; doc.remove( offset, len ); doc.insertString( offset, text, null); } finally { doc.atomicUnlock(); } } catch( BadLocationException exc ) { return false; //not sucessfull } return true; } /** @return the text this item would expand to. */ public String getItemText() { return text; } } public static class DefaultResultItem extends CompletionQuery.AbstractResultItem { /** The cache for component used for painting value of this * this component is reused, on every call to getPaintComponent it is * set up and then painted. By default, this component is hold opaque. */ static JLabel rubberStamp = new JLabel(); static { rubberStamp.setOpaque( true ); } /** Color used for painting text of non-selected item */ protected Color foreColor; public DefaultResultItem( String text, Color foreColor ) { super( text ); this.foreColor = foreColor; } public Component getPaintComponent( JList list, boolean isSelected, boolean cellHasFocus ) { rubberStamp.setText( " " + text ); // NOI18N if (isSelected) { rubberStamp.setBackground(list.getSelectionBackground()); rubberStamp.setForeground(list.getSelectionForeground()); } else { rubberStamp.setBackground(list.getBackground()); rubberStamp.setForeground( foreColor ); } return rubberStamp; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy