my Apps: * COOL MOVIE BROWSER (sports, tv on net) here * MONEY ON THREAD (personal finance) here * HIT-BALL (cute game) here



GXT - How to select items in non-editable ComboBox by pressing keys

We have a non-editable GXT ComboBox with quite numerous items (100-200), which is hard to select by scrolling (even if they are alphabetically ordered). It would be nice and faster to have the possibility to select items by typing the keys. Unfortunately this feature isn't built-in GXT non-editable combo-box, like it's done for the editable one.

In this case we can fix it by extending the ComboBox class and add to it a key listener and a timer. When we press a key we collect the chars into a buffer and then we look for the item that starts with that text. If we didn't type anything for more than 1 second, then we reset the buffer to allow trying another letters, if the one typed earlier aren't good.

*** The GXT solution is the implementation of the selectable combo-box (preferred ordered, but not a mandatory requirement) by keys is presented below:

public class SccComboBox<D extends ModelData> extends ComboBox<D> {
    private final StringBuilder buffer;
    private final DelayedTask resetBufferTimer; 


    /** constructor */
    public SccComboBox () {
        buffer = new StringBuilder();
resetBufferTimer = new DelayedTask(new Listener<BaseEvent>() {
@Override
public void handleEvent(final BaseEvent be) {
buffer.delete(0, buffer.length());
}
});
    }



    /**
     * {@inheritDoc}
     */
    @Override
    protected void onKeyPress(FieldEvent fe) {
        if (isExpanded()) {
            if (!fe.isSpecialKey()) {
buffer.append((char) fe.getKeyCode());
           }
           if (fe.getKeyCode() == KeyCodes.KEY_BACKSPACE) {
int idx = buffer_.length() - 1;
if (idx >= 0) {
                   buffer.deleteCharAt(idx);
}
           }


           for (D d : store.getModels()) {
String v = propertyEditor.getStringValue(d);
if (v.toLowerCase().startsWith(buffer.toString().toLowerCase())) {
                  select(d);
                  break;
}
           }


           /* timer timeout 1 second */
           resetBufferTimer.delay(1000);
}
        super.onKeyPress(fe);
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void expand() {
        buffer.delete(0, buffer.length());
        super.expand();
    }
}

** The solution for pure GWT implementation is similar with the above code, but with few small changes. We need to replace the DelayedTask with my previous pure GWT implementation of the DelayedTask, LastCallBurstEventsMgr, like in the below code:
  1. First of all, remove the resetBufferTimer local member variable from the SccComboBox, definition and constructor.
  2. Secondly, at the line /* timer timeout 1 second */ we replace the next code line with the following ones:

   /* timer timeout 1 second */
   LastCallBurstEventMgr.addEvent (new BurstEvent ("reset-buffer-timer", new Function() {
       public void execute () {
  buffer.delete(0, buffer.length());
       }
   }, 1000));

So, having this logic added to the ComboBox will resolve your "selection in long combo-box" problem.

Cheers!

3 comments:

  1. very good solution - it's working perfect for me. thx man

    ReplyDelete
  2. Nice and descriptive article. Check for more @ Stark Solutions

    ReplyDelete
  3. Thank you a lot. It works great :)

    ReplyDelete