Evolutionary Dawn

March 21, 2008

JSuggestionPanel (AKA JSuggestionField, CompletionTextField)

Filed under: Uncategorized — admin @ 1:22 pm

Also known as a JTextField that magically have a list appear after you hit ENTER or CompletionTextField.

Since I have not found a open source or version that is purchasable I decided to hack one together today and give it freely to the world. Hopefully this helps some one.

Here are my sources:

Java 1.5 API
(Of Course)

Netbeans Bean Tutorial

Randomness on the NET

Ok starting with the SuggestionPanel itself:

1
2
3
4
5
6
7
8
9
package com.mdb.widgets;
import com.mdb.interfaces.SearchableListModel;
import com.mdb.objects.DefaultSearchableListModel;
import java.awt.event.KeyEvent;
import java.io.Serializable;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
import org.jdesktop.layout.GroupLayout;
1
2
3
4
5
/**
* @author David Durst
*/
 
public class SuggestionPanel extends JPanel implements Serializable {
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
    private JList list;
    private Object selectedItem;
    private boolean list_visible = false;
    private SearchableListModel model = new DefaultSearchableListModel();
    public SuggestionPanel() {
        initComponents();
        list = new JList();
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        list.setModel(model);
        list.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                jListKeyPressed(evt);
            }
 
        });
        jPopupMenu1.add(list);
    }
    private void initComponents() {
        jPopupMenu1 = new javax.swing.JPopupMenu();
 
    searchStringTextField = new javax.swing.JTextField();
    searchStringTextField.addKeyListener(new java.awt.event.KeyAdapter() {
        public void keyPressed(java.awt.event.KeyEvent evt) {
            searchStringTextFieldKeyPressed(evt);
        }
    });
    GroupLayout layout = new GroupLayout(this);
    this.setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
        .add(searchStringTextField,GroupLayout.DEFAULT_SIZE, 197, Short.MAX_VALUE)
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(GroupLayout.LEADING)
        .add(searchStringTextField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
    );
 
    }
    private void jListKeyPressed(KeyEvent evt) {
        int kc = evt.getKeyCode();
        if(kc == KeyEvent.VK_ENTER) {
            jPopupMenu1.setVisible(false);
            selectedItem = model.getElementAt(list.getSelectedIndex());
            searchStringTextField.setText(selectedItem.toString());
            list_visible = false;
        }
    }
    private void searchStringTextFieldKeyPressed(java.awt.event.KeyEvent evt) {
        int kc = evt.getKeyCode();
        if(kc == KeyEvent.VK_ENTER) {
            String searchString = searchStringTextField.getText();
            model.search(searchString);
            jPopupMenu1.show(this,searchStringTextField.getX(),searchStringTextField.getY()+searchStringTextField.getHeight());
            list_visible = true;
            list.requestFocus();
            list.setSelectedIndex(list.getMinSelectionIndex());
        }
        else if(kc == KeyEvent.VK_DOWN && list_visible) {
            list.requestFocus();
            int index = list.getSelectedIndex();
            index++;
            if(index > list.getMaxSelectionIndex())
                list.setSelectedIndex(list.getMinSelectionIndex());
            else
                list.setSelectedIndex(index);
        }
        else if(kc == KeyEvent.VK_UP && list_visible) {
            list.requestFocus();
            int index = list.getSelectedIndex();
            index--;
            if(index < list.getMinSelectionIndex())
                list.setSelectedIndex(list.getMaxSelectionIndex());
            else
                list.setSelectedIndex(index);
        }
 
    }
 
    private javax.swing.JPopupMenu jPopupMenu1;
    private javax.swing.JTextField searchStringTextField;
 
    public SearchableListModel getModel() {
        return model;
    }
    public void setModel(SearchableListModel model) {
        list.setModel(model);
        this.model = model;
    }
    public Object getSelectedItem() {
        return selectedItem;
    }
 
}

Now on to the Interface for extending ListModel:

1
2
3
4
5
6
7
8
9
package com.mdb.interfaces;
import javax.swing.ListModel;
/**
 * @author David Durst
 */
 
public interface SearchableListModel extends ListModel {
    public void search(String text);
}

And now to the implementing class DefaultSearchableListModel:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.mdb.objects;
 
import com.mdb.interfaces.SearchableListModel;
import java.util.List;
import java.util.Vector;
import javax.swing.DefaultListModel;
/**
 * @author David Durst
 */
 
public class DefaultSearchableListModel extends DefaultListModel implements SearchableListModel {
    private List list = new Vector();
    public DefaultSearchableListModel() {
        list.add("Testing");
        list.add("David Smith");
        list.add("Ron Johnson");
        list.add("Nick Smith");
    }
    public void clear() {
        while(getSize() != 0) {
            remove(getSize()-1);
        }
    }
 
    public void search(final String text) {
        clear();
        String searchString = text.toLowerCase();
        for(Object o : list) {
            String os = o.toString();
            os = os.toLowerCase();
            if(os.contains(searchString)) {
                addElement(o);
 
            }
        }
    }
}

Attaching this to a Database should be fairly simple, you can hack that into a class that implements SearchableListModel, or

do some other type of magical binding vodoo.

Here is a Screen Shot

Screen shot

No Comments »

No comments yet.

RSS feed for comments on this post. TrackBack URL

Leave a comment

You must be logged in to post a comment.

Powered by WordPress