tags:

views:

1068

answers:

1

I'm using GWT/GXT and trying to create a "normal" ComboBox - one that you cannot type in, but you can type a single character and it will automatically go to the first item in the list that starts with that letter. So, I don't want it READONLY, I want it so that you cannot replace the text in it with your own text (can't type characters into it).

I cannot figure out how to get ComboBox or SimpleComboBox to do this. I've tried every combination of settings on it to no avail. I did see there is a GXT ListBox, but i need a component that extends from Field.

Is there really no way to do this or am I missing something?

+3  A: 

By using setEditable(false) and setForceSelection(true) and extending the class, you can accomplish this yourself (by watching for key presses on the widget).

First, the subclass:

package net.binarymuse.gwt.gxt.client;

import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.KeyListener;
import com.extjs.gxt.ui.client.widget.form.SimpleComboBox;

public class MySimpleComboBox<T extends String> extends SimpleComboBox<T> {

    public MySimpleComboBox() {
        super();
        this.addKeyListener(new KeyListener(){
            @Override
            public void componentKeyDown(ComponentEvent event)
            {
                // Get a reference to the combobox in question
                MySimpleComboBox<T> combo = MySimpleComboBox.this;

                // Get the character that has been pressed
                String sChar = String.valueOf((char) event.getKeyCode());
                // TODO - add some checking here to make sure the character is
                //        one we actually want to process

                // Make sure we have items in the store to iterate
                int numItems = combo.getStore().getCount();
                if(numItems == 0)
                    return;

                // Check each item in the store to see if it starts with our character
                for(int i = 0; i < numItems; i++)
                {
                    String value = combo.getStore().getAt(i).getValue();
                    // If it does, select it and return
                    if(value.startsWith(sChar) || value.startsWith(sChar.toUpperCase()))
                    {
                        MySimpleComboBox.this.setSimpleValue((T) value);
                        return;
                    }
                }
            }
        });
    }

}

And the test:

package net.binarymuse.gwt.gxt.client;

import com.extjs.gxt.ui.client.widget.form.SimpleComboBox;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;


public class GxtSandbox implements EntryPoint {

    public void onModuleLoad() {
        SimpleComboBox<String> box = new MySimpleComboBox<String>();
        box.add("One");
        box.add("Two");
        box.add("Three");
        box.setEditable(false);
        box.setForceSelection(true);

        RootPanel.get().add(box);
    }
}

Giving the combo box focus and pressing "T" should select "Two" in the list.

As is, the class always selects the first item in the list that starts with the character; however, it would not be difficult to modify it to make it select the next item in the list (as is typical with "real" combo boxes).

BinaryMuse
I guess i wasn't clear. I know I can do it all myself, I just assumed there must be a built-in way to do this with the proper options. Maybe there isn't?
VogonPoet
I don't see one that makes sense. The options that "you'd think" would invoke this behavior, don't. Perhaps it's a bug, or a good feature request.
BinaryMuse
Yeah - that's what I figured but I was hoping I had just missed something. Thanks.
VogonPoet
Ok, answering my own question (sort of) - ListBox does what I was looking for - it's non-editable and you can press a key while it's focused and it will go to the next match.
VogonPoet