dendini
dendini

Reputation: 3952

Weird java auto complete of JTextField special case

I have an autocompletion of JTextFields which so far seemed to work, however a specific subcase has appeared which is shown below: try inserting "em" and instead of "emanuele semani" autocompletion you get "eanuemeli li" which doesn't even exist in the list (the list containing only two items:

  1. emanuele semani
  2. manuemeli li

)

I know the names are weird however two books had these names..

import java.util.ArrayList;
import javax.swing.*;
import javax.swing.text.Document;
import AutoCompleteDocument;
import CompletionService;

public class AutoCompleteExample
{
    TitleService titleService;
    Document titleAutoCompleteDocument;
    JTextField titleField;

    private class TitleService extends CompletionService
    {
        public TitleService()
        {
            ArrayList<String> eventTitles = getBookTitles();
            for (int i = 0; eventTitles != null && i < eventTitles.size(); i++)
            {
                if (eventTitles.get(i) != null)
                {
                    data.add(eventTitles.get(i));
                }
            }
        }
    }

    public AutoCompleteExample()
    {
        JPanel panel = new JPanel();
        titleField = new JTextField();
        titleField.setColumns(50);
        panel.add(titleField);

        titleService = new TitleService();
        titleAutoCompleteDocument = new AutoCompleteDocument(titleService,
                titleField);

         JFrame frame = new JFrame();
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.add(panel);
         frame.setSize(700, 100);
         frame.setVisible(true);
         refreshCompletionServices();
    }

    public void refreshCompletionServices()
    {
        titleService = new TitleService();
        titleAutoCompleteDocument = new AutoCompleteDocument(titleService,
                titleField);
        titleField.setDocument(titleAutoCompleteDocument);
    }


    private ArrayList<String> getBookTitles()
    {
        ArrayList<String> titles = new ArrayList<>();
        titles.add("emanule semani");
        titles.add("manuemeli li");
        return titles;
    }

    public static void main(String args[])
    {
        AutoCompleteExample ex = new AutoCompleteExample();
    }
}

and CompletionService.java class is

import java.util.ArrayList;
import java.util.List;


public class CompletionService
{
    public List<String> data = new ArrayList<>();
    String autoComplete(String partialString)
    {
        String hit = null;
        for (String o : data)
        {
            if (o.toLowerCase().contains(partialString.toLowerCase()))
            {
                // CompletionService contract states that we only
                // should return completion for unique hits.
                if (hit == null)
                {
                    int index = o.toLowerCase().indexOf(partialString.toLowerCase());
                    hit = o.substring(index);
                }
                else
                {
                    if (hit.length() > o.length())
                    {
                        hit = o;
                    }
                }
            }
        }
        return hit;
    }
}

and the AUtoCompleteDocument.java is

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import javax.swing.text.PlainDocument;

public class AutoCompleteDocument extends PlainDocument
{
    private static final long serialVersionUID = 1L;
    private CompletionService completionService;
    private JTextComponent documentOwner;

    public AutoCompleteDocument(CompletionService service,
            JTextComponent documentOwner)
    {
        this.completionService = service;
        this.documentOwner = documentOwner;
    }

    protected String complete(String str)
    {
        Object o = completionService.autoComplete(str);
        return o == null ? null : o.toString();
    }

    @Override
    public void insertString(int offs, String str, AttributeSet a)
            throws BadLocationException
    {
        if (str == null || str.length() == 0)
        {
            return;
        }

        String text = getText(0, offs); // Current text.
        String completion = complete(text + str);
        int length = offs + str.length();
        if (completion != null && text.length() > 0)
        {
            str = completion.substring(length - 1);
            super.insertString(offs, str, a);
            documentOwner.select(length, getLength());
        }
        else
        {
            super.insertString(offs, str, a);
        }
    }
}

Upvotes: 0

Views: 760

Answers (2)

Vishal K
Vishal K

Reputation: 13066

You should replace

if (o.toLowerCase().contains(partialString.toLowerCase()))

to

if (o.toLowerCase().startsWith(partialString.toLowerCase()))

Upvotes: 1

mKorbel
mKorbel

Reputation: 109823

my answer is about Why to reinvent the wheel, use

Upvotes: 1

Related Questions