alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 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; } } }

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.