Ch5CompletionEditor.java Source code

Java tutorial

Introduction

Here is the source code for Ch5CompletionEditor.java

Source

/*
SWT/JFace in Action
GUI Design with Eclipse 3.0
Matthew Scarpino, Stephen Holder, Stanford Ng, and Laurent Mihalkovic
    
ISBN: 1932394273
    
Publisher: Manning
*/

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextListener;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.TextEvent;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.text.contentassist.CompletionProposal;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.ContextInformationValidator;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;

public class Ch5CompletionEditor extends Composite {
    private TextViewer textViewer;

    private WordTracker wordTracker;

    private static final int MAX_QUEUE_SIZE = 200;

    public Ch5CompletionEditor(Composite parent) {
        super(parent, SWT.NULL);
        wordTracker = new WordTracker(MAX_QUEUE_SIZE);
        buildControls();
    }

    private void buildControls() {
        setLayout(new FillLayout());
        textViewer = new TextViewer(this, SWT.MULTI | SWT.V_SCROLL);

        textViewer.setDocument(new Document());

        final ContentAssistant assistant = new ContentAssistant();
        assistant.setContentAssistProcessor(new RecentWordContentAssistProcessor(wordTracker),
                IDocument.DEFAULT_CONTENT_TYPE);

        assistant.install(textViewer);

        textViewer.getControl().addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                switch (e.keyCode) {
                case SWT.F1:
                    assistant.showPossibleCompletions();
                    break;
                default:
                    //ignore everything else
                }
            }
        });

        textViewer.addTextListener(new ITextListener() {
            public void textChanged(TextEvent e) {
                if (isWhitespaceString(e.getText())) {
                    wordTracker.add(findMostRecentWord(e.getOffset() - 1));
                }
            }
        });
    }

    protected String findMostRecentWord(int startSearchOffset) {
        int currOffset = startSearchOffset;
        char currChar;
        String word = "";
        try {
            while (currOffset > 0
                    && !Character.isWhitespace(currChar = textViewer.getDocument().getChar(currOffset))) {
                word = currChar + word;
                currOffset--;
            }
            return word;
        } catch (BadLocationException e) {
            e.printStackTrace();
            return null;
        }
    }

    protected boolean isWhitespaceString(String string) {
        StringTokenizer tokenizer = new StringTokenizer(string);
        //if there is at least 1 token, this string is not whitespace
        return !tokenizer.hasMoreTokens();
    }

}

class WordTracker {
    private int maxQueueSize;

    private List wordBuffer;

    private Map knownWords = new HashMap();

    public WordTracker(int queueSize) {
        maxQueueSize = queueSize;
        wordBuffer = new LinkedList();
    }

    public int getWordCount() {
        return wordBuffer.size();
    }

    public void add(String word) {
        if (wordIsNotKnown(word)) {
            flushOldestWord();
            insertNewWord(word);
        }
    }

    private void insertNewWord(String word) {
        wordBuffer.add(0, word);
        knownWords.put(word, word);
    }

    private void flushOldestWord() {
        if (wordBuffer.size() == maxQueueSize) {
            String removedWord = (String) wordBuffer.remove(maxQueueSize - 1);
            knownWords.remove(removedWord);
        }
    }

    private boolean wordIsNotKnown(String word) {
        return knownWords.get(word) == null;
    }

    public List suggest(String word) {
        List suggestions = new LinkedList();
        for (Iterator i = wordBuffer.iterator(); i.hasNext();) {
            String currWord = (String) i.next();
            if (currWord.startsWith(word)) {
                suggestions.add(currWord);
            }
        }
        return suggestions;
    }

}

class RecentWordContentAssistProcessor implements IContentAssistProcessor {
    private String lastError = null;

    private IContextInformationValidator contextInfoValidator;

    private WordTracker wordTracker;

    public RecentWordContentAssistProcessor(WordTracker tracker) {
        super();
        contextInfoValidator = new ContextInformationValidator(this);
        wordTracker = tracker;
    }

    public ICompletionProposal[] computeCompletionProposals(ITextViewer textViewer, int documentOffset) {
        IDocument document = textViewer.getDocument();
        int currOffset = documentOffset - 1;

        try {
            String currWord = "";
            char currChar;
            while (currOffset > 0 && !Character.isWhitespace(currChar = document.getChar(currOffset))) {
                currWord = currChar + currWord;
                currOffset--;
            }

            List suggestions = wordTracker.suggest(currWord);
            ICompletionProposal[] proposals = null;
            if (suggestions.size() > 0) {
                proposals = buildProposals(suggestions, currWord, documentOffset - currWord.length());
                lastError = null;
            }
            return proposals;
        } catch (BadLocationException e) {
            e.printStackTrace();
            lastError = e.getMessage();
            return null;
        }
    }

    private ICompletionProposal[] buildProposals(List suggestions, String replacedWord, int offset) {
        ICompletionProposal[] proposals = new ICompletionProposal[suggestions.size()];
        int index = 0;
        for (Iterator i = suggestions.iterator(); i.hasNext();) {
            String currSuggestion = (String) i.next();
            proposals[index] = new CompletionProposal(currSuggestion, offset, replacedWord.length(),
                    currSuggestion.length());
            index++;
        }
        return proposals;
    }

    public IContextInformation[] computeContextInformation(ITextViewer textViewer, int documentOffset) {
        lastError = "No Context Information available";
        return null;
    }

    public char[] getCompletionProposalAutoActivationCharacters() {
        //we always wait for the user to explicitly trigger completion
        return null;
    }

    public char[] getContextInformationAutoActivationCharacters() {
        //we have no context information
        return null;
    }

    public String getErrorMessage() {
        return lastError;
    }

    public IContextInformationValidator getContextInformationValidator() {
        return contextInfoValidator;
    }
}