Java/Swing Components/ComboBox

Материал из Java эксперт
Перейти к: навигация, поиск

Содержание

Auto complete ComboBox

 
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
import java.util.List;
import javax.swing.JTextField;
import javax.swing.text.*;
public class jexpAutoTextField extends JTextField {
  class AutoDocument extends PlainDocument {
    public void replace(int i, int j, String s, AttributeSet attributeset)
        throws BadLocationException {
      super.remove(i, j);
      insertString(i, s, attributeset);
    }
    public void insertString(int i, String s, AttributeSet attributeset)
        throws BadLocationException {
      if (s == null || "".equals(s))
        return;
      String s1 = getText(0, i);
      String s2 = getMatch(s1 + s);
      int j = (i + s.length()) - 1;
      if (isStrict && s2 == null) {
        s2 = getMatch(s1);
        j--;
      } else if (!isStrict && s2 == null) {
        super.insertString(i, s, attributeset);
        return;
      }
      if (autoComboBox != null && s2 != null)
        autoComboBox.setSelectedValue(s2);
      super.remove(0, getLength());
      super.insertString(0, s2, attributeset);
      setSelectionStart(j + 1);
      setSelectionEnd(getLength());
    }
    public void remove(int i, int j) throws BadLocationException {
      int k = getSelectionStart();
      if (k > 0)
        k--;
      String s = getMatch(getText(0, k));
      if (!isStrict && s == null) {
        super.remove(i, j);
      } else {
        super.remove(0, getLength());
        super.insertString(0, s, null);
      }
      if (autoComboBox != null && s != null)
        autoComboBox.setSelectedValue(s);
      try {
        setSelectionStart(k);
        setSelectionEnd(getLength());
      } catch (Exception exception) {
      }
    }
  }
  public jexpAutoTextField(List list) {
    isCaseSensitive = false;
    isStrict = true;
    autoComboBox = null;
    if (list == null) {
      throw new IllegalArgumentException("values can not be null");
    } else {
      dataList = list;
      init();
      return;
    }
  }
  jexpAutoTextField(List list, jexpAutoComboBox b) {
    isCaseSensitive = false;
    isStrict = true;
    autoComboBox = null;
    if (list == null) {
      throw new IllegalArgumentException("values can not be null");
    } else {
      dataList = list;
      autoComboBox = b;
      init();
      return;
    }
  }
  private void init() {
    setDocument(new AutoDocument());
    if (isStrict && dataList.size() > 0)
      setText(dataList.get(0).toString());
  }
  private String getMatch(String s) {
    for (int i = 0; i < dataList.size(); i++) {
      String s1 = dataList.get(i).toString();
      if (s1 != null) {
        if (!isCaseSensitive
            && s1.toLowerCase().startsWith(s.toLowerCase()))
          return s1;
        if (isCaseSensitive && s1.startsWith(s))
          return s1;
      }
    }
    return null;
  }
  public void replaceSelection(String s) {
    AutoDocument _lb = (AutoDocument) getDocument();
    if (_lb != null)
      try {
        int i = Math.min(getCaret().getDot(), getCaret().getMark());
        int j = Math.max(getCaret().getDot(), getCaret().getMark());
        _lb.replace(i, j - i, s, null);
      } catch (Exception exception) {
      }
  }
  public boolean isCaseSensitive() {
    return isCaseSensitive;
  }
  public void setCaseSensitive(boolean flag) {
    isCaseSensitive = flag;
  }
  public boolean isStrict() {
    return isStrict;
  }
  public void setStrict(boolean flag) {
    isStrict = flag;
  }
  public List getDataList() {
    return dataList;
  }
  public void setDataList(List list) {
    if (list == null) {
      throw new IllegalArgumentException("values can not be null");
    } else {
      dataList = list;
      return;
    }
  }
  private List dataList;
  private boolean isCaseSensitive;
  private boolean isStrict;
  private jexpAutoComboBox autoComboBox;
}
import java.awt.event.ItemEvent;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.plaf.basic.BasicComboBoxEditor;
public class jexpAutoComboBox extends JComboBox {
  private class AutoTextFieldEditor extends BasicComboBoxEditor {
    private jexpAutoTextField getAutoTextFieldEditor() {
      return (jexpAutoTextField) editor;
    }
    AutoTextFieldEditor(java.util.List list) {
      editor = new jexpAutoTextField(list, jexpAutoComboBox.this);
    }
  }
  public jexpAutoComboBox(java.util.List list) {
    isFired = false;
    autoTextFieldEditor = new AutoTextFieldEditor(list);
    setEditable(true);
    setModel(new DefaultComboBoxModel(list.toArray()) {
      protected void fireContentsChanged(Object obj, int i, int j) {
        if (!isFired)
          super.fireContentsChanged(obj, i, j);
      }
    });
    setEditor(autoTextFieldEditor);
  }
  public boolean isCaseSensitive() {
    return autoTextFieldEditor.getAutoTextFieldEditor().isCaseSensitive();
  }
  public void setCaseSensitive(boolean flag) {
    autoTextFieldEditor.getAutoTextFieldEditor().setCaseSensitive(flag);
  }
  public boolean isStrict() {
    return autoTextFieldEditor.getAutoTextFieldEditor().isStrict();
  }
  public void setStrict(boolean flag) {
    autoTextFieldEditor.getAutoTextFieldEditor().setStrict(flag);
  }
  public java.util.List getDataList() {
    return autoTextFieldEditor.getAutoTextFieldEditor().getDataList();
  }
  public void setDataList(java.util.List list) {
    autoTextFieldEditor.getAutoTextFieldEditor().setDataList(list);
    setModel(new DefaultComboBoxModel(list.toArray()));
  }
  void setSelectedValue(Object obj) {
    if (isFired) {
      return;
    } else {
      isFired = true;
      setSelectedItem(obj);
      fireItemStateChanged(new ItemEvent(this, 701, selectedItemReminder,
          1));
      isFired = false;
      return;
    }
  }
  protected void fireActionEvent() {
    if (!isFired)
      super.fireActionEvent();
  }
  private AutoTextFieldEditor autoTextFieldEditor;
  private boolean isFired;
}





Block ComboBox Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1) */

import java.awt.ruponent;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Vector;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JSeparator;
import javax.swing.ListCellRenderer;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
/**
 * @version 1.0 12/25/98
 */
public class BlockComboBoxExample extends JFrame {
  final String SEPARATOR = "SEPARATOR";
  public BlockComboBoxExample() {
    super("Block ComboBox Example");
    String[][] str = { { "A", "B", "C" }, { "1", "2", "3" },
        { "abc", "def", "ghi" } };
    JComboBox combo = new JComboBox(makeVectorData(str));
    combo.setRenderer(new ComboBoxRenderer());
    combo.addActionListener(new BlockComboListener(combo));
    getContentPane().setLayout(new FlowLayout());
    getContentPane().add(combo);
    setSize(300, 100);
    setVisible(true);
  }
  private Vector makeVectorData(String[][] str) {
    boolean needSeparator = false;
    Vector data = new Vector();
    for (int i = 0; i < str.length; i++) {
      if (needSeparator) {
        data.addElement(SEPARATOR);
      }
      for (int j = 0; j < str[i].length; j++) {
        data.addElement(str[i][j]);
        needSeparator = true;
      }
    }
    return data;
  }
  public static void main(String args[]) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    BlockComboBoxExample frame = new BlockComboBoxExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
  class ComboBoxRenderer extends JLabel implements ListCellRenderer {
    JSeparator separator;
    public ComboBoxRenderer() {
      setOpaque(true);
      setBorder(new EmptyBorder(1, 1, 1, 1));
      separator = new JSeparator(JSeparator.HORIZONTAL);
    }
    public Component getListCellRendererComponent(JList list, Object value,
        int index, boolean isSelected, boolean cellHasFocus) {
      String str = (value == null) ? "" : value.toString();
      if (SEPARATOR.equals(str)) {
        return separator;
      }
      if (isSelected) {
        setBackground(list.getSelectionBackground());
        setForeground(list.getSelectionForeground());
      } else {
        setBackground(list.getBackground());
        setForeground(list.getForeground());
      }
      setFont(list.getFont());
      setText(str);
      return this;
    }
  }
  class BlockComboListener implements ActionListener {
    JComboBox combo;
    Object currentItem;
    BlockComboListener(JComboBox combo) {
      this.rubo = combo;
      combo.setSelectedIndex(0);
      currentItem = combo.getSelectedItem();
    }
    public void actionPerformed(ActionEvent e) {
      String tempItem = (String) combo.getSelectedItem();
      if (SEPARATOR.equals(tempItem)) {
        combo.setSelectedItem(currentItem);
      } else {
        currentItem = tempItem;
      }
    }
  }
}





ComboBox color chooser (Windows Color Chooser)

 
(From http://swinglabs.org/downloads.jsp)





ComboBox Menu Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html

import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import javax.swing.plaf.basic.BasicArrowButton;
/**
 * @version 1.0 05/10/99
 */
public class ComboBoxMenuExample extends JFrame {
  public ComboBoxMenuExample() {
    super("ComboBoxMenu Example");
    String[] itemStr = { "name", "Red", "Blue", "number", "255,0,0",
        "0,0,255",
        // separator
        "system", "control", "controlHighlight", "controlShadow",
        "text" };
    JMenuItem[] menuItems = new JMenuItem[7];
    menuItems[0] = new JMenuItem(itemStr[1]);
    menuItems[1] = new JMenuItem(itemStr[2]);
    menuItems[2] = new JMenuItem(itemStr[4]);
    menuItems[3] = new JMenuItem(itemStr[5]);
    menuItems[4] = new JMenuItem(itemStr[8]);
    menuItems[5] = new JMenuItem(itemStr[9]);
    menuItems[6] = new JMenuItem(itemStr[10]);
    JMenu[] menus = new JMenu[4];
    menus[0] = new JMenu(itemStr[0]);
    menus[1] = new JMenu(itemStr[3]);
    menus[2] = new JMenu(itemStr[6]);
    menus[3] = new JMenu(itemStr[7]);
    menus[0].add(menuItems[0]);
    menus[0].add(menuItems[1]);
    menus[1].add(menuItems[2]);
    menus[1].add(menuItems[3]);
    menus[3].add(menuItems[4]);
    menus[3].add(menuItems[5]);
    menus[2].add(menus[3]);
    menus[2].add(menuItems[6]);
    JMenu menu = ComboMenuBar.createMenu(menuItems[0].getText());
    menu.add(menus[0]);
    menu.add(menus[1]);
    menu.addSeparator();
    menu.add(menus[2]);
    ComboMenuBar comboMenu = new ComboMenuBar(menu);
    JComboBox combo = new JComboBox();
    combo.addItem(itemStr[1]);
    combo.addItem(itemStr[2]);
    combo.addItem(itemStr[4]);
    combo.addItem(itemStr[5]);
    combo.addItem(itemStr[8]);
    combo.addItem(itemStr[9]);
    combo.addItem(itemStr[10]);
    getContentPane().setLayout(new FlowLayout());
    getContentPane().add(new ComboPanel("Fake ComboBox", comboMenu));
    getContentPane().add(new ComboPanel("ComboBox", combo));
  }
  class ComboPanel extends JPanel {
    ComboPanel(String title, JComponent c) {
      setLayout(new FlowLayout());
      setBorder(new TitledBorder(title));
      add(c);
    }
  }
  public static void main(String args[]) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    ComboBoxMenuExample frame = new ComboBoxMenuExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.setSize(370, 100);
    frame.setVisible(true);
  }
}
class ComboMenuBar extends JMenuBar {
  JMenu menu;
  Dimension preferredSize;
  public ComboMenuBar(JMenu menu) {
    this.menu = menu;
    Color color = UIManager.getColor("Menu.selectionBackground");
    UIManager.put("Menu.selectionBackground", UIManager
        .getColor("Menu.background"));
    menu.updateUI();
    UIManager.put("Menu.selectionBackground", color);
    MenuItemListener listener = new MenuItemListener();
    setListener(menu, listener);
    add(menu);
  }
  class MenuItemListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      JMenuItem item = (JMenuItem) e.getSource();
      menu.setText(item.getText());
      menu.requestFocus();
    }
  }
  private void setListener(JMenuItem item, ActionListener listener) {
    if (item instanceof JMenu) {
      JMenu menu = (JMenu) item;
      int n = menu.getItemCount();
      for (int i = 0; i < n; i++) {
        setListener(menu.getItem(i), listener);
      }
    } else if (item != null) { // null means separator
      item.addActionListener(listener);
    }
  }
  public String getSelectedItem() {
    return menu.getText();
  }
  public void setPreferredSize(Dimension size) {
    preferredSize = size;
  }
  public Dimension getPreferredSize() {
    if (preferredSize == null) {
      Dimension sd = super.getPreferredSize();
      Dimension menuD = getItemSize(menu);
      Insets margin = menu.getMargin();
      Dimension retD = new Dimension(menuD.width, margin.top
          + margin.bottom + menuD.height);
      menu.setPreferredSize(retD);
      preferredSize = retD;
    }
    return preferredSize;
  }
  private Dimension getItemSize(JMenu menu) {
    Dimension d = new Dimension(0, 0);
    int n = menu.getItemCount();
    for (int i = 0; i < n; i++) {
      Dimension itemD;
      JMenuItem item = menu.getItem(i);
      if (item instanceof JMenu) {
        itemD = getItemSize((JMenu) item);
      } else if (item != null) {
        itemD = item.getPreferredSize();
      } else {
        itemD = new Dimension(0, 0); // separator
      }
      d.width = Math.max(d.width, itemD.width);
      d.height = Math.max(d.height, itemD.height);
    }
    return d;
  }
  public static class ComboMenu extends JMenu {
    ArrowIcon iconRenderer;
    public ComboMenu(String label) {
      super(label);
      iconRenderer = new ArrowIcon(SwingConstants.SOUTH, true);
      setBorder(new EtchedBorder());
      setIcon(new BlankIcon(null, 11));
      setHorizontalTextPosition(JButton.LEFT);
      setFocusPainted(true);
    }
    public void paintComponent(Graphics g) {
      super.paintComponent(g);
      Dimension d = this.getPreferredSize();
      int x = Math.max(0, d.width - iconRenderer.getIconWidth() - 3);
      int y = Math.max(0,
          (d.height - iconRenderer.getIconHeight()) / 2 - 2);
      iconRenderer.paintIcon(this, g, x, y);
    }
  }
  public static JMenu createMenu(String label) {
    return new ComboMenu(label);
  }
}
class ArrowIcon implements Icon, SwingConstants {
  private static final int DEFAULT_SIZE = 11;
  //private static final int DEFAULT_SIZE = 5;
  private int size;
  private int iconSize;
  private int direction;
  private boolean isEnabled;
  private BasicArrowButton iconRenderer;
  public ArrowIcon(int direction, boolean isPressedView) {
    this(DEFAULT_SIZE, direction, isPressedView);
  }
  public ArrowIcon(int iconSize, int direction, boolean isEnabled) {
    this.size = iconSize / 2;
    this.iconSize = iconSize;
    this.direction = direction;
    this.isEnabled = isEnabled;
    iconRenderer = new BasicArrowButton(direction);
  }
  public void paintIcon(Component c, Graphics g, int x, int y) {
    iconRenderer.paintTriangle(g, x, y, size, direction, isEnabled);
  }
  public int getIconWidth() {
    //int retCode;
    switch (direction) {
    case NORTH:
    case SOUTH:
      return iconSize;
    case EAST:
    case WEST:
      return size;
    }
    return iconSize;
  }
  public int getIconHeight() {
    switch (direction) {
    case NORTH:
    case SOUTH:
      return size;
    case EAST:
    case WEST:
      return iconSize;
    }
    return size;
  }
}
class BlankIcon implements Icon {
  private Color fillColor;
  private int size;
  public BlankIcon() {
    this(null, 11);
  }
  public BlankIcon(Color color, int size) {
    //UIManager.getColor("control")
    //UIManager.getColor("controlShadow")
    fillColor = color;
    this.size = size;
  }
  public void paintIcon(Component c, Graphics g, int x, int y) {
    if (fillColor != null) {
      g.setColor(fillColor);
      g.drawRect(x, y, size - 1, size - 1);
    }
  }
  public int getIconWidth() {
    return size;
  }
  public int getIconHeight() {
    return size;
  }
}





Disabled ComboBox Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html

/* (swing1.1) */

import java.awt.ruponent;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
/**
 * @version 1.0 12/26/98
 */
public class DisabledComboBoxExample extends JFrame {
  public DisabledComboBoxExample() {
    super("Disabled Item ComboBox Example");
    Object[] items = { new ComboItem("A"), new ComboItem("B"),
        new ComboItem("1", false), new ComboItem("2", false),
        new ComboItem("abc"), new ComboItem("def") };
    JComboBox combo = new JComboBox(items);
    combo.setRenderer(new ComboRenderer());
    combo.addActionListener(new ComboListener(combo));
    getContentPane().setLayout(new FlowLayout());
    getContentPane().add(combo);
    setSize(300, 100);
    setVisible(true);
  }
  public static void main(String args[]) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    DisabledComboBoxExample frame = new DisabledComboBoxExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
  class ComboRenderer extends JLabel implements ListCellRenderer {
    public ComboRenderer() {
      setOpaque(true);
      setBorder(new EmptyBorder(1, 1, 1, 1));
    }
    public Component getListCellRendererComponent(JList list, Object value,
        int index, boolean isSelected, boolean cellHasFocus) {
      if (isSelected) {
        setBackground(list.getSelectionBackground());
        setForeground(list.getSelectionForeground());
      } else {
        setBackground(list.getBackground());
        setForeground(list.getForeground());
      }
      if (!((CanEnable) value).isEnabled()) {
        setBackground(list.getBackground());
        setForeground(UIManager.getColor("Label.disabledForeground"));
      }
      setFont(list.getFont());
      setText((value == null) ? "" : value.toString());
      return this;
    }
  }
  class ComboListener implements ActionListener {
    JComboBox combo;
    Object currentItem;
    ComboListener(JComboBox combo) {
      this.rubo = combo;
      combo.setSelectedIndex(0);
      currentItem = combo.getSelectedItem();
    }
    public void actionPerformed(ActionEvent e) {
      Object tempItem = combo.getSelectedItem();
      if (!((CanEnable) tempItem).isEnabled()) {
        combo.setSelectedItem(currentItem);
      } else {
        currentItem = tempItem;
      }
    }
  }
  class ComboItem implements CanEnable {
    Object obj;
    boolean isEnable;
    ComboItem(Object obj, boolean isEnable) {
      this.obj = obj;
      this.isEnable = isEnable;
    }
    ComboItem(Object obj) {
      this(obj, true);
    }
    public boolean isEnabled() {
      return isEnable;
    }
    public void setEnabled(boolean isEnable) {
      this.isEnable = isEnable;
    }
    public String toString() {
      return obj.toString();
    }
  }
}
interface CanEnable {
  public void setEnabled(boolean isEnable);
  public boolean isEnabled();
}





JComboBox: adding automatic completion-Adding automatic completion

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
Adding automatic completion
Now, to do automatic completion instead of just automatic selection access to the combo box" 
editor is needed. Otherwise it would not be possible to highlight the completed part using 
selection (see above). I added the whole JComboBox to the constructor. The selection should 
start right after the last character that was inserted (at position offs+str.length()).
*/
import javax.swing.*;
import javax.swing.text.*;
public class S04FirstAutoCompletion extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    
    public S04FirstAutoCompletion(final JComboBox comboBox) {
        this.ruboBox = comboBox;
        model = comboBox.getModel();
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        super.remove(offs, len);
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        // insert the string into the document
        super.insertString(offs, str, a);
        // lookup and select a matching item
        Object item = lookupItem(getText(0, getLength()));
        setSelectedItem(item);
        // remove all text and insert the completed string
        super.remove(0, getLength());
        super.insertString(0, item.toString(), a);
        // select the completed part
        JTextComponent editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        editor.setSelectionStart(offs+str.length());
        editor.setSelectionEnd(getLength());
    }
    
    private void setSelectedItem(Object item) {
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object lookupItem(String pattern) {
        // iterate over all items
        for (int i=0, n=model.getSize(); i < n; i++) {
            Object currentItem = model.getElementAt(i);
            // current item starts with the pattern?
            if (currentItem.toString().startsWith(pattern)) {
                return currentItem;
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // get the combo boxes editor component
        JTextComponent editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        // change the editor"s document
        editor.setDocument(new S04FirstAutoCompletion(comboBox));
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Adding automatic selection

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
Adding automatic selection
To actually select an item in the combo box access to the combo box" model is needed inside 
our document. It can be passed as a parameter to the constructor (omitted here, see 
sourcecode). Adding some kind of automatic selection inside insertString...
*/
import javax.swing.*;
import javax.swing.text.*;
public class S02BrokenAutoSelection extends PlainDocument {
    ComboBoxModel model;
    
    public S02BrokenAutoSelection(ComboBoxModel model) {
        this.model = model;
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        System.out.println("insert " + str + " at " + offs);
        // insert the string into the document
        super.insertString(offs, str, a);
        // get the resulting string
        String content = getText(0, getLength());
        // lookup a matching item
        Object item = lookupItem(content);
        // select the item (or deselect if null)
        if(item!=model.getSelectedItem()) System.out.println("Selecting "" + item + """);
        model.setSelectedItem(item);
    }
    
    private Object lookupItem(String pattern) {
        // iterate over all items
        for (int i=0, n=model.getSize(); i < n; i++) {
            Object currentItem = model.getElementAt(i);
            // current item starts with the pattern?
            if (currentItem.toString().startsWith(pattern)) {
                return currentItem;
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // get the combo boxes editor component
        JTextComponent editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        // change the editor"s document
        editor.setDocument(new S02BrokenAutoSelection(comboBox.getModel()));
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Backspace

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
Backspace
One inconvenience is that after hitting backspace the selection is not moved backwards as one would expect. I first thought that this be would easy to implement. However, it came out that there are some tramps one should be aware of.
First, have a look when and how (parameters) the remove method is called...

*/
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class S13RemoveTest extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    JTextComponent editor;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    boolean hidePopupOnFocusLoss;
    
    public S13RemoveTest(final JComboBox comboBox) {
        this.ruboBox = comboBox;
        model = comboBox.getModel();
        editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        editor.setDocument(this);
        comboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!selecting) highlightCompletedText(0);
            }
        });
        editor.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
            }
        });
        // Bug 5100422 on Java 1.5: Editable JComboBox won"t hide popup when tabbing out
        hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5");
        // Highlight whole text when gaining focus
        editor.addFocusListener(new FocusAdapter() {
            public void focusGained(FocusEvent e) {
                highlightCompletedText(0);
            }
            public void focusLost(FocusEvent e) {
                // Workaround for Bug 5100422 - Hide Popup on focus loss
                if (hidePopupOnFocusLoss) comboBox.setPopupVisible(false);
            }
        });
        // Handle initially selected object
        Object selected = comboBox.getSelectedItem();
        if (selected!=null) setText(selected.toString());
        highlightCompletedText(0);
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        System.out.println("remove " + len + " at " + offs);
        super.remove(offs, len);
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        // insert the string into the document
        super.insertString(offs, str, a);
        // lookup and select a matching item
        Object item = lookupItem(getText(0, getLength()));
        if (item != null) {
            setSelectedItem(item);
        } else {
            // keep old item selected if there is no match
            item = comboBox.getSelectedItem();
            // imitate no insert (later on offs will be incremented by str.length(): selection won"t move forward)
            offs = offs-str.length();
            // provide feedback to the user that his input has been received but can not be accepted
            comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
        }
        setText(item.toString());
        // select the completed part
        highlightCompletedText(offs+str.length());
    }
    
    private void setText(String text) {
        try {
            // remove all text and insert the completed string
            super.remove(0, getLength());
            super.insertString(0, text, null);
        } catch (BadLocationException e) {
            throw new RuntimeException(e.toString());
        }
    }
    
    private void highlightCompletedText(int start) {
        editor.setCaretPosition(getLength());
        editor.moveCaretPosition(start);
    }
    
    private void setSelectedItem(Object item) {
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object lookupItem(String pattern) {
        Object selectedItem = model.getSelectedItem();
        // only search for a different item if the currently selected does not match
        if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
            return selectedItem;
        } else {
            // iterate over all items
            for (int i=0, n=model.getSize(); i < n; i++) {
                Object currentItem = model.getElementAt(i);
                // current item starts with the pattern?
                if (startsWithIgnoreCase(currentItem.toString(), pattern)) {
                    return currentItem;
                }
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    // checks if str1 starts with str2 - ignores case
    private boolean startsWithIgnoreCase(String str1, String str2) {
        return str1.toUpperCase().startsWith(str2.toUpperCase());
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // change the editor"s document
        new S13RemoveTest(comboBox);
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Backspace 2

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
You will have noticed that the method has been called on every key stroke whether you hit 
backspace or not. This happens because the selected text will always be removed before 
inserting a new letter!
Now, when should the selection move backwards and when should some text really be removed? 
Inside the remove method the information is needed if it was called because the user hit 
backspace or if it has been called for other reasons. There already is a KeyListener on the 
combo box" editor, so a boolean member variable named hitBackspace can be introduced that 
indicates whether the last key that has been pressed was backspace or not...
*/
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class S14KeyListener extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    JTextComponent editor;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    boolean hidePopupOnFocusLoss;
    boolean hitBackspace=false;
    
    public S14KeyListener(final JComboBox comboBox) {
        this.ruboBox = comboBox;
        model = comboBox.getModel();
        editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        editor.setDocument(this);
        comboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!selecting) highlightCompletedText(0);
            }
        });
        editor.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
                hitBackspace=false;
                if (e.getKeyCode()==KeyEvent.VK_BACK_SPACE) hitBackspace=true;
            }
        });
        // Bug 5100422 on Java 1.5: Editable JComboBox won"t hide popup when tabbing out
        hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5");
        // Highlight whole text when gaining focus
        editor.addFocusListener(new FocusAdapter() {
            public void focusGained(FocusEvent e) {
                highlightCompletedText(0);
            }
            public void focusLost(FocusEvent e) {
                // Workaround for Bug 5100422 - Hide Popup on focus loss
                if (hidePopupOnFocusLoss) comboBox.setPopupVisible(false);
            }
        });
        // Handle initially selected object
        Object selected = comboBox.getSelectedItem();
        if (selected!=null) setText(selected.toString());
        highlightCompletedText(0);
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        if (hitBackspace) {
            System.out.println("Backspace was hit: moving the selection backwards");
            // user hit backspace => move the selection backwards
            // old item keeps being selected
            highlightCompletedText(offs-1);
        } else {
            System.out.println("Real remove: delegating to super.remove(" + offs + "," + len + ")");
            super.remove(offs, len);
        }
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        // insert the string into the document
        super.insertString(offs, str, a);
        // lookup and select a matching item
        Object item = lookupItem(getText(0, getLength()));
        if (item != null) {
            setSelectedItem(item);
        } else {
            // keep old item selected if there is no match
            item = comboBox.getSelectedItem();
            // imitate no insert (later on offs will be incremented by str.length(): selection won"t move forward)
            offs = offs-str.length();
            // provide feedback to the user that his input has been received but can not be accepted
            comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
        }
        setText(item.toString());
        // select the completed part
        highlightCompletedText(offs+str.length());
    }
    
    private void setText(String text) {
        try {
            // remove all text and insert the completed string
            super.remove(0, getLength());
            super.insertString(0, text, null);
        } catch (BadLocationException e) {
            throw new RuntimeException(e.toString());
        }
    }
    
    private void highlightCompletedText(int start) {
        editor.setCaretPosition(getLength());
        editor.moveCaretPosition(start);
    }
    
    private void setSelectedItem(Object item) {
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object lookupItem(String pattern) {
        Object selectedItem = model.getSelectedItem();
        // only search for a different item if the currently selected does not match
        if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
            return selectedItem;
        } else {
            // iterate over all items
            for (int i=0, n=model.getSize(); i < n; i++) {
                Object currentItem = model.getElementAt(i);
                // current item starts with the pattern?
                if (startsWithIgnoreCase(currentItem.toString(), pattern)) {
                    return currentItem;
                }
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    // checks if str1 starts with str2 - ignores case
    private boolean startsWithIgnoreCase(String str1, String str2) {
        return str1.toUpperCase().startsWith(str2.toUpperCase());
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // change the editor"s document
        new S14KeyListener(comboBox);
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Binary Lookup and Performance

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
Binary Lookup & Performance
*/
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import java.lang.reflect.Field;
import javax.swing.plaf.basic.BasicComboBoxUI;
public class S19PrototypeValue extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    JTextComponent editor;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    boolean hidePopupOnFocusLoss;
    boolean hitBackspace=false;
    boolean hitBackspaceOnSelection;
    
    public S19PrototypeValue(final JComboBox comboBox) {
        this.ruboBox = comboBox;
        model = comboBox.getModel();
        editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        editor.setDocument(this);
        comboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!selecting) highlightCompletedText(0);
            }
        });
        editor.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
                hitBackspace=false;
                switch (e.getKeyCode()) {
                    // determine if the pressed key is backspace (needed by the remove method)
                    case KeyEvent.VK_BACK_SPACE : hitBackspace=true;
                                                  hitBackspaceOnSelection=editor.getSelectionStart()!=editor.getSelectionEnd();
                                                  break;
                    // ignore delete key
                    case KeyEvent.VK_DELETE : e.consume();
                                              comboBox.getToolkit().beep();
                                              break;
                }
            }
        });
        // Bug 5100422 on Java 1.5: Editable JComboBox won"t hide popup when tabbing out
        hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5");
        // Highlight whole text when gaining focus
        editor.addFocusListener(new FocusAdapter() {
            public void focusGained(FocusEvent e) {
                highlightCompletedText(0);
            }
            public void focusLost(FocusEvent e) {
                // Workaround for Bug 5100422 - Hide Popup on focus loss
                if (hidePopupOnFocusLoss) comboBox.setPopupVisible(false);
            }
        });
        setPrototypeValue();
        // Handle initially selected object
        Object selected = comboBox.getSelectedItem();
        if (selected!=null) setText(selected.toString());
        highlightCompletedText(0);
    }
    
    public void setPrototypeValue() {
        JList list = getListBox();
        setPrototypeValue(getPrototypeValue(list), list);
    }
    
    void setPrototypeValue(Object value, JList list) {
        comboBox.setPrototypeDisplayValue(value);
        list.setPrototypeCellValue(value);
    }
    
    Object getPrototypeValue(JList list) {
        Object prototypeValue=null;
        double prototypeWidth=0;
        ListCellRenderer renderer = comboBox.getRenderer();
        for (int i=0, n=model.getSize(); i<n; i++) {
            Object value = model.getElementAt(i);
            java.awt.ruponent c = renderer.getListCellRendererComponent(list, value, i, false, false);
            double width = c.getPreferredSize().getWidth();
            if (width>prototypeWidth) {
                prototypeWidth=width;
                prototypeValue=value;
            }
        }
        return prototypeValue;
    }
    
    JList getListBox() {
        JList listBox;
        try {
            Field field = JComponent.class.getDeclaredField("ui");
            field.setAccessible(true);
            BasicComboBoxUI ui = (BasicComboBoxUI) field.get(comboBox);
            field = BasicComboBoxUI.class.getDeclaredField("listBox");
            field.setAccessible(true);
            listBox = (JList) field.get(ui);
        } catch (NoSuchFieldException nsfe) {
            throw new RuntimeException(nsfe);
        } catch (IllegalAccessException iae) {
            throw new RuntimeException(iae);
        }
        return listBox;
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        if (hitBackspace) {
            // user hit backspace => move the selection backwards
            // old item keeps being selected
            if (offs>0) {
                if (hitBackspaceOnSelection) offs--;
            } else {
                // User hit backspace with the cursor positioned on the start => beep
                comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
            }
            highlightCompletedText(offs);
        } else {
            super.remove(offs, len);
        }
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        // insert the string into the document
        super.insertString(offs, str, a);
        // lookup and select a matching item
        Object item = lookupItem(getText(0, getLength()));
        if (item != null) {
            setSelectedItem(item);
        } else {
            // keep old item selected if there is no match
            item = comboBox.getSelectedItem();
            // imitate no insert (later on offs will be incremented by str.length(): selection won"t move forward)
            offs = offs-str.length();
            // provide feedback to the user that his input has been received but can not be accepted
            comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
        }
        setText(item.toString());
        // select the completed part
        highlightCompletedText(offs+str.length());
    }
    
    private void setText(String text) {
        try {
            // remove all text and insert the completed string
            super.remove(0, getLength());
            super.insertString(0, text, null);
        } catch (BadLocationException e) {
            throw new RuntimeException(e.toString());
        }
    }
    
    private void highlightCompletedText(int start) {
        editor.setCaretPosition(getLength());
        editor.moveCaretPosition(start);
    }
    
    private void setSelectedItem(Object item) {
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object lookupItem(String pattern) {
        Object selectedItem = model.getSelectedItem();
        // only search for a different item if the currently selected does not match
        if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
            return selectedItem;
        } else {
            // iterate over all items
            for (int i=0, n=model.getSize(); i < n; i++) {
                Object currentItem = model.getElementAt(i);
                // current item starts with the pattern?
                if (startsWithIgnoreCase(currentItem.toString(), pattern)) return currentItem;
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    // checks if str1 starts with str2 - ignores case
    private boolean startsWithIgnoreCase(String str1, String str2) {
        return str1.toUpperCase().startsWith(str2.toUpperCase());
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // change the editor"s document
        new S19PrototypeValue(comboBox);
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Binay Lookup 2

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import java.lang.reflect.Field;
import javax.swing.plaf.basic.BasicComboBoxUI;
public class S20BinaryLookup extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    JTextComponent editor;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    boolean hidePopupOnFocusLoss;
    boolean hitBackspace=false;
    boolean hitBackspaceOnSelection;
    
    public S20BinaryLookup(final JComboBox comboBox) {
        this.ruboBox = comboBox;
        model = comboBox.getModel();
        editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        editor.setDocument(this);
        comboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!selecting) highlightCompletedText(0);
            }
        });
        editor.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
                hitBackspace=false;
                switch (e.getKeyCode()) {
                    // determine if the pressed key is backspace (needed by the remove method)
                    case KeyEvent.VK_BACK_SPACE : hitBackspace=true;
                    hitBackspaceOnSelection=editor.getSelectionStart()!=editor.getSelectionEnd();
                    break;
                    // ignore delete key
                    case KeyEvent.VK_DELETE : e.consume();
                    comboBox.getToolkit().beep();
                    break;
                }
            }
        });
        // Bug 5100422 on Java 1.5: Editable JComboBox won"t hide popup when tabbing out
        hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5");
        // Highlight whole text when gaining focus
        editor.addFocusListener(new FocusAdapter() {
            public void focusGained(FocusEvent e) {
                highlightCompletedText(0);
            }
            public void focusLost(FocusEvent e) {
                // Workaround for Bug 5100422 - Hide Popup on focus loss
                if (hidePopupOnFocusLoss) comboBox.setPopupVisible(false);
            }
        });
        setPrototypeValue();
        // Handle initially selected object
        Object selected = comboBox.getSelectedItem();
        if (selected!=null) setText(selected.toString());
        highlightCompletedText(0);
    }
    
    public void setPrototypeValue() {
        JList list = getListBox();
        setPrototypeValue(getPrototypeValue(list), list);
    }
    
    void setPrototypeValue(Object value, JList list) {
        comboBox.setPrototypeDisplayValue(value);
        list.setPrototypeCellValue(value);
    }
    
    Object getPrototypeValue(JList list) {
        Object prototypeValue=null;
        double prototypeWidth=0;
        ListCellRenderer renderer = comboBox.getRenderer();
        for (int i=0, n=model.getSize(); i<n; i++) {
            Object value = model.getElementAt(i);
            java.awt.ruponent c = renderer.getListCellRendererComponent(list, value, i, false, false);
            double width = c.getPreferredSize().getWidth();
            if (width>prototypeWidth) {
                prototypeWidth=width;
                prototypeValue=value;
            }
        }
        return prototypeValue;
    }
    
    JList getListBox() {
        JList listBox;
        try {
            Field field = JComponent.class.getDeclaredField("ui");
            field.setAccessible(true);
            BasicComboBoxUI ui = (BasicComboBoxUI) field.get(comboBox);
            field = BasicComboBoxUI.class.getDeclaredField("listBox");
            field.setAccessible(true);
            listBox = (JList) field.get(ui);
        } catch (NoSuchFieldException nsfe) {
            throw new RuntimeException(nsfe);
        } catch (IllegalAccessException iae) {
            throw new RuntimeException(iae);
        }
        return listBox;
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        if (hitBackspace) {
            // user hit backspace => move the selection backwards
            // old item keeps being selected
            if (offs>0) {
                if (hitBackspaceOnSelection) offs--;
            } else {
                // User hit backspace with the cursor positioned on the start => beep
                comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
            }
            highlightCompletedText(offs);
        } else {
            super.remove(offs, len);
        }
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        // insert the string into the document
        super.insertString(offs, str, a);
        // lookup and select a matching item
        Object item = lookupItem(getText(0, getLength()));
        if (item != null) {
            setSelectedItem(item);
        } else {
            // keep old item selected if there is no match
            item = comboBox.getSelectedItem();
            // imitate no insert (later on offs will be incremented by str.length(): selection won"t move forward)
            offs = offs-str.length();
            // provide feedback to the user that his input has been received but can not be accepted
            comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
        }
        setText(item.toString());
        // select the completed part
        highlightCompletedText(offs+str.length());
    }
    
    private void setText(String text) {
        try {
            // remove all text and insert the completed string
            super.remove(0, getLength());
            super.insertString(0, text, null);
        } catch (BadLocationException e) {
            throw new RuntimeException(e.toString());
        }
    }
    
    private void highlightCompletedText(int start) {
        editor.setCaretPosition(getLength());
        editor.moveCaretPosition(start);
    }
    
    private void setSelectedItem(Object item) {
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object binaryLookup(String pattern) {
        int bottom=0, top=model.getSize()-1;
        int pos=0;
        Object item=null;
        // search for a matching item
        while (bottom<=top) {
            pos = (bottom + top) >> 1;
            item=model.getElementAt(pos);
            int compare = compareStartIgnoreCase(item.toString(), pattern);
            if (compare==0) {
                break;
            } else if (compare>0) {
                bottom=pos+1;
            } else {
                top=pos-1;
            }
        }
        // if no item matches bottom is greater than top
        if (bottom>top) return null;
        // search for the _first_ matching item
        for (int i=bottom; i<pos; i++) {
            Object anItem=model.getElementAt(i);
            if (startsWithIgnoreCase(anItem.toString(), pattern)) {
                return anItem;
            }
        }
        return item;
    }
    
    private Object lookupItem(String pattern) {
        Object selectedItem = model.getSelectedItem();
        // only search for a different item if the currently selected does not match
        if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
            return selectedItem;
        }
        Object item = binaryLookup(pattern);
        return item;
    }
    
    // checks if str1 starts with str2 - ignores case
    private boolean startsWithIgnoreCase(String str1, String str2) {
        return str1.toUpperCase().startsWith(str2.toUpperCase());
    }
    
    private static int compareStartIgnoreCase(String str1, String str2) {
        char[] ch1 = str1.toCharArray();
        char[] ch2 = str2.toCharArray();
        for (int i=0, n=ch2.length<ch1.length?ch2.length:ch1.length; i<n; i++) {
            int diff = Character.toUpperCase(ch2[i])-Character.toUpperCase(ch1[i]);
            if (diff != 0) {
                return diff;
            }
        }
        if (ch1.length<ch2.length) return 1;
        return 0;
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // change the editor"s document
        new S20BinaryLookup(comboBox);
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Case insensitive matching

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
Case insensitive matching
The typical usecases for an autocompleting combo box will hardly need case sensitive matches. 
It is easy to modify the lookup mechanism to ignore case, so that the user does not have to 
care about typing "E" or "e". This short method does the trick...
*/

import javax.swing.*;
import javax.swing.text.*;
public class S05CaseInsensitive extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    JTextComponent editor;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    
    public S05CaseInsensitive(final JComboBox comboBox) {
        this.ruboBox = comboBox;
        model = comboBox.getModel();
        editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        super.remove(offs, len);
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        // insert the string into the document
        super.insertString(offs, str, a);
        // lookup and select a matching item
        Object item = lookupItem(getText(0, getLength()));
        setSelectedItem(item);
        setText(item.toString());
        // select the completed part
        highlightCompletedText(offs+str.length());
    }
    
    private void setText(String text) throws BadLocationException {
        // remove all text and insert the completed string
        super.remove(0, getLength());
        super.insertString(0, text, null);
    }
    
    private void highlightCompletedText(int start) {
        editor.setSelectionStart(start);
        editor.setSelectionEnd(getLength());
    }
    
    private void setSelectedItem(Object item) {
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object lookupItem(String pattern) {
        // iterate over all items
        for (int i=0, n=model.getSize(); i < n; i++) {
            Object currentItem = model.getElementAt(i);
            // current item starts with the pattern?
            if (startsWithIgnoreCase(currentItem.toString(), pattern)) {
                System.out.println(""" + currentItem + "" matches pattern "" + pattern + """);
                return currentItem;
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    // checks if str1 starts with str2 - ignores case
    private boolean startsWithIgnoreCase(String str1, String str2) {
        return str1.toUpperCase().startsWith(str2.toUpperCase());
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // get the combo boxes editor component
        JTextComponent editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        // change the editor"s document
        editor.setDocument(new S05CaseInsensitive(comboBox));
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Catching user input

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
Catching user input
Although there are possibly many ways to catch the input to a text component, only one is 
shown here. It is the same that once has been suggested by Sun"s Java Tutorial to add 
validation to text components (replaced by JFormattedTextField ). It suggests to get control 
over the user input by implementing a specialized Document overriding the methods 
insertString and remove. Input to the text component can then be rejected, accepted or 
transformed in these two methods.
Let us start with an editable combo box that is not accepting anything to demonstrate how to 
change the editor component"s document.
*/
import javax.swing.*;
import javax.swing.text.*;
public class S01BadDocument extends PlainDocument {
    
    public void insertString(int offs, String str, AttributeSet a) {
        // reject the insert but print a message on the console
        System.out.println("insert " + str + " at " + offs);
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // get the combo boxes editor component
        JTextComponent editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        // change the editor"s document
        editor.setDocument(new S01BadDocument());
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Cursor position

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
Cursor position
This is really a minor addition and more a question of personal preference. You might have 
noticed that the cursor normally is located at the end of the completed text. If you prefer 
it to be at the beginning of the selected text try this...
private void highlightCompletedText(int start) {
  editor.setCaretPosition(getLength());
  editor.moveCaretPosition(start);
}
*/
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class S10CursorPosition extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    JTextComponent editor;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    
    public S10CursorPosition(final JComboBox comboBox) {
        this.ruboBox = comboBox;
        model = comboBox.getModel();
        editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        comboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!selecting) highlightCompletedText(0);
            }
        });
        editor.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
            }
        });
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        super.remove(offs, len);
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        // insert the string into the document
        super.insertString(offs, str, a);
        // lookup and select a matching item
        Object item = lookupItem(getText(0, getLength()));
        if (item != null) {
            setSelectedItem(item);
        } else {
            // keep old item selected if there is no match
            item = comboBox.getSelectedItem();
            // imitate no insert (later on offs will be incremented by str.length(): selection won"t move forward)
            offs = offs-str.length();
            // provide feedback to the user that his input has been received but can not be accepted
            comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
        }
        setText(item.toString());
        // select the completed part
        highlightCompletedText(offs+str.length());
    }
    
    private void setText(String text) throws BadLocationException {
        // remove all text and insert the completed string
        super.remove(0, getLength());
        super.insertString(0, text, null);
    }
    
    private void highlightCompletedText(int start) {
        editor.setCaretPosition(getLength());
        editor.moveCaretPosition(start);
    }
    
    private void setSelectedItem(Object item) {
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object lookupItem(String pattern) {
        Object selectedItem = model.getSelectedItem();
        // only search for a different item if the currently selected does not match
        if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
            return selectedItem;
        } else {
            // iterate over all items
            for (int i=0, n=model.getSize(); i < n; i++) {
                Object currentItem = model.getElementAt(i);
                // current item starts with the pattern?
                if (startsWithIgnoreCase(currentItem.toString(), pattern)) {
                    return currentItem;
                }
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    // checks if str1 starts with str2 - ignores case
    private boolean startsWithIgnoreCase(String str1, String str2) {
        return str1.toUpperCase().startsWith(str2.toUpperCase());
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // get the combo boxes editor component
        JTextComponent editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        // change the editor"s document
        editor.setDocument(new S10CursorPosition(comboBox));
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Fixed Auto Selection

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
import javax.swing.*;
import javax.swing.text.*;
public class S03FixedAutoSelection extends PlainDocument {
    ComboBoxModel model;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    
    public S03FixedAutoSelection(ComboBoxModel model) {
        this.model = model;
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        super.remove(offs, len);
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        System.out.println("insert " + str + " at " + offs);
        // insert the string into the document
        super.insertString(offs, str, a);
        // get the resulting string
        String content = getText(0, getLength());
        // lookup a matching item
        Object item = lookupItem(content);
        // select the item (or deselect if null)
        if(item!=model.getSelectedItem()) System.out.println("Selecting "" + item + """);
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object lookupItem(String pattern) {
        // iterate over all items
        for (int i=0, n=model.getSize(); i < n; i++) {
            Object currentItem = model.getElementAt(i);
            // current item starts with the pattern?
            if (currentItem.toString().startsWith(pattern)) {
                return currentItem;
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // get the combo boxes editor component
        JTextComponent editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        // change the editor"s document
        editor.setDocument(new S03FixedAutoSelection(comboBox.getModel()));
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Handling focus loss

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
Handling focus loss
Another situation that needs highlighting of the complete text is when the user switches to another gui control (e.g. pressing the tabulator key). Otherwise the partial selection would still be there when the user returns to the combo box. Highlighting the complete text when the combo box loses focus could be a solution. However, switching the focus via mouse will not lead to the desired behaviour then: The cursor gets positioned by the mouse click and therefore the prior selection is removed. A better solution is to highlight the text when the focus is gained.
// Highlight whole text when gaining focus
editor.addFocusListener(new FocusAdapter() {
  public void focusGained(FocusEvent e) {
    highlightCompletedText(0);
  }
});
The popup list is hidden automatically when the user hits enter on most JDKs. The latest Java 1.5 release from Sun contains a bug and keeps the popup list visible. The popup list can"t be hidden for all JDK versions as this might lead to malfunctioning. A workaround could look like this...
// Bug 5100422 on Java 1.5: Editable JComboBox won"t hide popup when tabbing out hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5");
// Highlight whole text when gaining focus
editor.addFocusListener(new FocusAdapter() {
  [...]
  public void focusLost(FocusEvent e) {
    // Workaround for Bug 5100422 - Hide Popup on focus loss
    if (hidePopupOnFocusLoss) comboBox.setPopupVisible(false);
  }
});

*/
import javax.swing.*;
import javax.swing.text.*;
import java.awt.event.*;
public class S12FocusLost extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    JTextComponent editor;
    boolean hidePopupOnFocusLoss;
    
    public S12FocusLost(JComboBox comboBox) {
        this.ruboBox = comboBox;
        comboBox.setEditable(true);
        model = comboBox.getModel();
        editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        editor.setDocument(this);
        // Bug 5100422 on Java 1.5: Editable JComboBox won"t hide popup when tabbing out
        hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5");
        // Highlight whole text when focus gets lost
        editor.addFocusListener(new FocusAdapter() {
            public void focusLost(FocusEvent e) {
                highlightCompletedText(0);
                // Workaround for Bug 5100422 - Hide Popup on focus loss
                if (hidePopupOnFocusLoss) S12FocusLost.this.ruboBox.setPopupVisible(false);
            }
        });
        // Highlight whole text when user hits enter
        editor.addKeyListener(new KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent e) {
                if (e.getKeyCode() == e.VK_ENTER) {
                    highlightCompletedText(0);
                }
            }
        });
        
        // Handle initially selected object
        Object selected = comboBox.getSelectedItem();
        if (selected != null) editor.setText(selected.toString());
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // construct the resulting string
        String currentText = getText(0, getLength());
        String beforeOffset = currentText.substring(0, offs);
        String afterOffset = currentText.substring(offs, currentText.length());
        String futureText = beforeOffset + str + afterOffset;
        
        // lookup and select a matching item
        Object item = lookupItem(futureText);
        if (item != null) {
            comboBox.setSelectedItem(item);
        } else {
            // keep old item selected if there is no match
            item = comboBox.getSelectedItem();
            // imitate no insert (later on offs will be incremented by str.length(): selection won"t move forward)
            offs = offs-str.length();
            // provide feedback to the user that his input has been received but can not be accepted
            comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
        }
        
        // remove all text and insert the completed string
        super.remove(0, getLength());
        super.insertString(0, item.toString(), a);
        
        // if the user selects an item via mouse the the whole string will be inserted.
        // highlight the entire text if this happens.
        if (item.toString().equals(str) && offs==0) {
            highlightCompletedText(0);
        } else {
            highlightCompletedText(offs+str.length());
            // show popup when the user types
            comboBox.setPopupVisible(true);
        }
    }
    
    private void highlightCompletedText(int start) {
        editor.setCaretPosition(getLength());
        editor.moveCaretPosition(start);
    }
    
    private Object lookupItem(String pattern) {
        Object selectedItem = model.getSelectedItem();
        // only search for a different item if the currently selected does not match
        if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
            return selectedItem;
        } else {
            // iterate over all items
            for (int i=0, n=model.getSize(); i < n; i++) {
                Object currentItem = model.getElementAt(i);
                // current item starts with the pattern?
                if (startsWithIgnoreCase(currentItem.toString(), pattern)) {
                    return currentItem;
                }
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    // checks if str1 starts with str2 - ignores case
    private boolean startsWithIgnoreCase(String str1, String str2) {
        return str1.toUpperCase().startsWith(str2.toUpperCase());
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        new S12FocusLost(comboBox);
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().setLayout(new java.awt.FlowLayout());
        frame.getContentPane().add(comboBox);
        frame.getContentPane().add(new JTextField("I wan"t more focus!"));
        frame.pack(); frame.setVisible(true);
    }
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Handling the initial selection

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
Handling the initial selection
It is a quiet annoying that the initially selected item is not shown in the combo box. This 
can be easily changed in the constructor of the auto completing document.
*/
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class S11InitialSelection extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    JTextComponent editor;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    
    public S11InitialSelection(final JComboBox comboBox) {
        this.ruboBox = comboBox;
        model = comboBox.getModel();
        editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        editor.setDocument(this);
        comboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!selecting) highlightCompletedText(0);
            }
        });
        editor.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
            }
        });
        // Handle initially selected object
        Object selected = comboBox.getSelectedItem();
        if (selected!=null) setText(selected.toString());
        highlightCompletedText(0);
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        super.remove(offs, len);
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        // insert the string into the document
        super.insertString(offs, str, a);
        // lookup and select a matching item
        Object item = lookupItem(getText(0, getLength()));
        if (item != null) {
            setSelectedItem(item);
        } else {
            // keep old item selected if there is no match
            item = comboBox.getSelectedItem();
            // imitate no insert (later on offs will be incremented by str.length(): selection won"t move forward)
            offs = offs-str.length();
            // provide feedback to the user that his input has been received but can not be accepted
            comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
        }
        setText(item.toString());
        // select the completed part
        highlightCompletedText(offs+str.length());
    }
    
    private void setText(String text) {
        try {
            // remove all text and insert the completed string
            super.remove(0, getLength());
            super.insertString(0, text, null);
        } catch (BadLocationException e) {
            throw new RuntimeException(e.toString());
        }
    }
    
    private void highlightCompletedText(int start) {
        editor.setCaretPosition(getLength());
        editor.moveCaretPosition(start);
    }
    
    private void setSelectedItem(Object item) {
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object lookupItem(String pattern) {
        Object selectedItem = model.getSelectedItem();
        // only search for a different item if the currently selected does not match
        if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
            return selectedItem;
        } else {
            // iterate over all items
            for (int i=0, n=model.getSize(); i < n; i++) {
                Object currentItem = model.getElementAt(i);
                // current item starts with the pattern?
                if (startsWithIgnoreCase(currentItem.toString(), pattern)) {
                    return currentItem;
                }
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    // checks if str1 starts with str2 - ignores case
    private boolean startsWithIgnoreCase(String str1, String str2) {
        return str1.toUpperCase().startsWith(str2.toUpperCase());
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // change the editor"s document
        new S11InitialSelection(comboBox);
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Highlight complete text

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
Highlight complete text when the user selects an item via mouse
When the user selects an item via mouse or using the cursor keys, the text is not highlighted. 
When the user select an item directly, the insertString method is called once with the 
complete string. Inside this method only completed text is highlighted which in this case is 
none, as the call already contained the complete string.
A solution is to highlight the complete text whenever an item gets selected and this 
selection was not initiated by the autocompletion mechanism. This can be achieved using an 
ActionListener...
*/
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class S08MouseCursor extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    JTextComponent editor;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    
    public S08MouseCursor(final JComboBox comboBox) {
        this.ruboBox = comboBox;
        model = comboBox.getModel();
        editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        comboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!selecting) highlightCompletedText(0);
            }
        });
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        super.remove(offs, len);
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        // insert the string into the document
        super.insertString(offs, str, a);
        // lookup and select a matching item
        Object item = lookupItem(getText(0, getLength()));
        if (item != null) {
            setSelectedItem(item);
        } else {
            // keep old item selected if there is no match
            item = comboBox.getSelectedItem();
            // imitate no insert (later on offs will be incremented by str.length(): selection won"t move forward)
            offs = offs-str.length();
            // provide feedback to the user that his input has been received but can not be accepted
            comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
        }
        
        setText(item.toString());
        
        // select the completed part
        highlightCompletedText(offs+str.length());
    }
    
    private void setText(String text) throws BadLocationException {
        // remove all text and insert the completed string
        super.remove(0, getLength());
        super.insertString(0, text, null);
    }
    
    private void highlightCompletedText(int start) {
        editor.setSelectionStart(start);
        editor.setSelectionEnd(getLength());
    }
    
    private void setSelectedItem(Object item) {
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object lookupItem(String pattern) {
        Object selectedItem = model.getSelectedItem();
        // only search for a different item if the currently selected does not match
        if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
            return selectedItem;
        } else {
            // iterate over all items
            for (int i=0, n=model.getSize(); i < n; i++) {
                Object currentItem = model.getElementAt(i);
                // current item starts with the pattern?
                if (startsWithIgnoreCase(currentItem.toString(), pattern)) {
                    return currentItem;
                }
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    // checks if str1 starts with str2 - ignores case
    private boolean startsWithIgnoreCase(String str1, String str2) {
        return str1.toUpperCase().startsWith(str2.toUpperCase());
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // get the combo boxes editor component
        JTextComponent editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        // change the editor"s document
        editor.setDocument(new S08MouseCursor(comboBox));
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Ignore input that does not match

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
Ignore input that does not match
If the user entered a key that does not match any item you get a NullPointerException. 
Of course this is not acceptable. A small enhancement in the insertString method will 
ignore "invalid" input.
*/
import javax.swing.*;
import javax.swing.text.*;
public class S07IgnoreNoMatch extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    JTextComponent editor;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    
    public S07IgnoreNoMatch(final JComboBox comboBox) {
        this.ruboBox = comboBox;
        model = comboBox.getModel();
        editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        super.remove(offs, len);
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        // insert the string into the document
        super.insertString(offs, str, a);
        // lookup and select a matching item
        Object item = lookupItem(getText(0, getLength()));
        if (item != null) {
            setSelectedItem(item);
        } else {
            // keep old item selected if there is no match
            item = comboBox.getSelectedItem();
            // imitate no insert (later on offs will be incremented by str.length(): selection won"t move forward)
            offs = offs-str.length();
            // provide feedback to the user that his input has been received but can not be accepted
            comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
        }
        setText(item.toString());
        // select the completed part
        highlightCompletedText(offs+str.length());
    }
    
    private void setText(String text) throws BadLocationException {
        // remove all text and insert the completed string
        super.remove(0, getLength());
        super.insertString(0, text, null);
    }
    
    private void highlightCompletedText(int start) {
        editor.setSelectionStart(start);
        editor.setSelectionEnd(getLength());
    }
    
    private void setSelectedItem(Object item) {
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object lookupItem(String pattern) {
        Object selectedItem = model.getSelectedItem();
        // only search for a different item if the currently selected does not match
        if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
            return selectedItem;
        } else {
            // iterate over all items
            for (int i=0, n=model.getSize(); i < n; i++) {
                Object currentItem = model.getElementAt(i);
                // current item starts with the pattern?
                if (startsWithIgnoreCase(currentItem.toString(), pattern)) {
                    return currentItem;
                }
            }
        }
        // no item starts with the pattern => return null
        System.out.println("No item matches pattern "" + pattern + """);
        return null;
    }
    
    // checks if str1 starts with str2 - ignores case
    private boolean startsWithIgnoreCase(String str1, String str2) {
        return str1.toUpperCase().startsWith(str2.toUpperCase());
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // get the combo boxes editor component
        JTextComponent editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        // change the editor"s document
        editor.setDocument(new S07IgnoreNoMatch(comboBox));
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Maximum Match

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
Maximum Match
This feature is about reducing the amount of key strokes a user has to do to select an item. 
In our five name example it is obvious that when the user types "J" he either means "Jordi", 
"Jordina" or "Jorge". All three of them start with "Jor". This can be taken into account when 
making the selection of the completed text. A picture makes it clear how this mechanism is 
supposed to work...
The user needs only two keystrokes instead of four to select "Jorge". This feature is not a 
really big advantage in the five name case from this article, but imagine a combo box with a 
list of chemical substances to choose from - like...
    * ...
    * 2-Chloro-2-methylbutane
    * 2-Chloro-2-methylpropane, Reagent
    * 2-Chloro-3-pyridinol
    * 2-Chloro-5-nitrobenzaldehyde
    * 2-Chloro-5-nitropyridine
    * 2-Chloro-5-methylphenol
    * 2-Chloromethylquinoline Hydrochloride
    * 2-Chlorophenylhydrazine Hydrochloride
    * 2-Chloropropane
    * ...
In cases like this one you might consider the maximum match feature (e.g. it takes 4 
keystrokes instead of 18 to select the second entry).
However, take care in other circumstances: users don"t like things happening out of their 
control. This feature can produce more confusion than clarity.
Enough warnings - how is it implemented?
As before, an item has been looked up in regard to the user"s input. Now an iteration is done 
over all items again and other items that would have matched the user"s input are collected. 
All these candidates are compared to find out if they have a common starting text. The common 
starting text won"t be highlighted after the completion as if it was entered by the user. The 
main method to consider does the comparison...
// calculates how many characters are predetermined by the given pattern.
private int getMaximumMatchingOffset(String pattern, Object selectedItem) {
  String selectedAsString=selectedItem.toString();
  int match=selectedAsString.length();
  // look for items that match the given pattern
  for (int i=0, n=model.getSize(); i < n; i++) {
    String itemAsString = model.getElementAt(i).toString();
    if (startsWithIgnoreCase(itemAsString, pattern)) {
      // current item matches the pattern
      // how many leading characters have the selected and the current item in common?
      int tmpMatch=equalStartLength(itemAsString, selectedAsString);
      if (tmpMatch < match) match=tmpMatch;
    }
  }
  return match;
}
Other modifications have been made to the insert method.
*/
import javax.swing.*;
import javax.swing.text.*;
import java.awt.event.*;
public class S16MaximumMatch extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    JTextComponent editor;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    boolean hidePopupOnFocusLoss;
    boolean hitBackspace=false;
    boolean hitBackspaceOnSelection;
    
    public S16MaximumMatch(final JComboBox comboBox) {
        this.ruboBox = comboBox;
        model = comboBox.getModel();
        editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        editor.setDocument(this);
        comboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!selecting) highlightCompletedText(0);
            }
        });
        editor.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
                hitBackspace=false;
                switch (e.getKeyCode()) {
                    // determine if the pressed key is backspace (needed by the remove method)
                    case KeyEvent.VK_BACK_SPACE : hitBackspace=true;
                                                  hitBackspaceOnSelection=editor.getSelectionStart()!=editor.getSelectionEnd();
                                                  break;
                    // ignore delete key
                    case KeyEvent.VK_DELETE : e.consume();
                                              comboBox.getToolkit().beep();
                                              break;
                }
            }
        });
        // Bug 5100422 on Java 1.5: Editable JComboBox won"t hide popup when tabbing out
        hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5");
        // Highlight whole text when gaining focus
        editor.addFocusListener(new FocusAdapter() {
            public void focusGained(FocusEvent e) {
                highlightCompletedText(0);
            }
            public void focusLost(FocusEvent e) {
                // Workaround for Bug 5100422 - Hide Popup on focus loss
                if (hidePopupOnFocusLoss) comboBox.setPopupVisible(false);
            }
        });
        // Handle initially selected object
        Object selected = comboBox.getSelectedItem();
        if (selected!=null) setText(selected.toString());
        highlightCompletedText(0);
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        if (hitBackspace) {
            // user hit backspace => move the selection backwards
            // old item keeps being selected
            if (offs>0) {
                if (hitBackspaceOnSelection) offs--;
            } else {
                // User hit backspace with the cursor positioned on the start => beep
                comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
            }
            highlightCompletedText(offs);
        } else {
            super.remove(offs, len);
        }
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        // insert the string into the document
        super.insertString(offs, str, a);
        // lookup and select a matching item
        boolean match=false;
        Object item = lookupItem(getText(0, getLength()));
        if (item != null) {
            match=true;
            setSelectedItem(item);
        } else {
            // keep old item selected if there is no match
            item = comboBox.getSelectedItem();
            // imitate no insert (later on offs will be incremented by str.length(): selection won"t move forward)
            offs = offs-str.length();
            // provide feedback to the user that his input has been received but can not be accepted
            comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
        }
        if (match) offs = getMaximumMatchingOffset(getText(0, getLength()), item);
        else offs+=str.length();
        setText(item.toString());
        // select the completed part
        highlightCompletedText(offs);
    }
    
    private void setText(String text) {
        try {
            // remove all text and insert the completed string
            super.remove(0, getLength());
            super.insertString(0, text, null);
        } catch (BadLocationException e) {
            throw new RuntimeException(e.toString());
        }
    }
    
    private void highlightCompletedText(int start) {
        editor.setCaretPosition(getLength());
        editor.moveCaretPosition(start);
    }
    
    private void setSelectedItem(Object item) {
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object lookupItem(String pattern) {
        Object selectedItem = model.getSelectedItem();
        // only search for a different item if the currently selected does not match
        if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
            return selectedItem;
        } else {
            // iterate over all items
            for (int i=0, n=model.getSize(); i < n; i++) {
                Object currentItem = model.getElementAt(i);
                // current item starts with the pattern?
                if (startsWithIgnoreCase(currentItem.toString(), pattern)) {
                    return currentItem;
                }
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    // checks if str1 starts with str2 - ignores case
    private boolean startsWithIgnoreCase(String str1, String str2) {
        return str1.toUpperCase().startsWith(str2.toUpperCase());
    }
    
    // calculates how many characters are predetermined by the given pattern.
    private int getMaximumMatchingOffset(String pattern, Object selectedItem) {
        String selectedAsString=selectedItem.toString();
        int match=selectedAsString.length();
        // look for items that match the given pattern
        for (int i=0, n=model.getSize(); i < n; i++) {
            String itemAsString = model.getElementAt(i).toString();
            if (startsWithIgnoreCase(itemAsString, pattern)) {
                // current item matches the pattern
                // how many leading characters have the selected and the current item in common?
                int tmpMatch=equalStartLength(itemAsString, selectedAsString);
                if (tmpMatch < match) match=tmpMatch;
            }
        }
        return match;
    }
    
    // returns how many leading characters two strings have in common?
    private static int equalStartLength(String str1, String str2) {
        char[] ch1 = str1.toUpperCase().toCharArray();
        char[] ch2 = str2.toUpperCase().toCharArray();
        int n = ch1.length>ch2.length?ch2.length:ch1.length;
        for (int i=0; i<n; i++) {
            if (ch1[i]!=ch2[i]) return i;
        }
        return n;
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // change the editor"s document
        new S16MaximumMatch(comboBox);
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Non-strict matching

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
Non-strict matching
I was asked if it is possible to do non-strict matching - allowing the user to enter an item 
that is not (yet) contained in the combo box. This one is fairly easy to implement. Instead 
of rejecting non-matching input, accept it is accepted. The rejecting section inside the 
insert method...
if (item != null) {
  setSelectedItem(item);
} else {
  // keep old item selected if there is no match
  item = comboBox.getSelectedItem();
  // imitate no insert
  // (later on offs will be incremented by str.length(): selection won"t move forward)
  offs = offs-str.length();
  // provide feedback to the user that his input has been received but can not be accepted
  UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
}
setText(item.toString());
// select the completed part
highlightCompletedText(offs+str.length());
...to accept all input it can be replaced by...
boolean listContainsSelectedItem = true;
if (item == null) {
  // no item matches => use the current input as selected item
  item=getText(0, getLength());
  listContainsSelectedItem=false;
}
setText(item.toString());
// select the completed part
if (listContainsSelectedItem) highlightCompletedText(offs+str.length());;
*/
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class S17NonStrict extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    JTextComponent editor;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    boolean hidePopupOnFocusLoss;
    boolean hitBackspace=false;
    boolean hitBackspaceOnSelection;
    
    public S17NonStrict(final JComboBox comboBox) {
        this.ruboBox = comboBox;
        model = comboBox.getModel();
        editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        editor.setDocument(this);
        comboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!selecting) highlightCompletedText(0);
            }
        });
        editor.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
                hitBackspace=false;
                switch (e.getKeyCode()) {
                    // determine if the pressed key is backspace (needed by the remove method)
                    case KeyEvent.VK_BACK_SPACE : hitBackspace=true;
                                                  hitBackspaceOnSelection=editor.getSelectionStart()!=editor.getSelectionEnd();
                                                  break;
                }
            }
        });
        // Bug 5100422 on Java 1.5: Editable JComboBox won"t hide popup when tabbing out
        hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5");
        // Highlight whole text when gaining focus
        editor.addFocusListener(new FocusAdapter() {
            public void focusGained(FocusEvent e) {
                highlightCompletedText(0);
            }
            public void focusLost(FocusEvent e) {
                // Workaround for Bug 5100422 - Hide Popup on focus loss
                if (hidePopupOnFocusLoss) comboBox.setPopupVisible(false);
            }
        });
        // Handle initially selected object
        Object selected = comboBox.getSelectedItem();
        if (selected!=null) setText(selected.toString());
        highlightCompletedText(0);
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        if (hitBackspace) {
            // user hit backspace => move the selection backwards
            // old item keeps being selected
            if (offs>0) {
                if (hitBackspaceOnSelection) offs--;
            } else {
                // User hit backspace with the cursor positioned on the start => beep
                comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
            }
            highlightCompletedText(offs);
        } else {
            super.remove(offs, len);
        }
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        // insert the string into the document
        super.insertString(offs, str, a);
        // lookup and select a matching item
        Object item = lookupItem(getText(0, getLength()));
        
        boolean listContainsSelectedItem = true;
        if (item == null) {
            // no item matches => use the current input as selected item
            item=getText(0, getLength());
            listContainsSelectedItem=false;
        }
        setSelectedItem(item);
        setText(item.toString());
        // select the completed part
        if (listContainsSelectedItem) highlightCompletedText(offs+str.length());
    }
    
    private void setText(String text) {
        try {
            // remove all text and insert the completed string
            super.remove(0, getLength());
            super.insertString(0, text, null);
        } catch (BadLocationException e) {
            throw new RuntimeException(e.toString());
        }
    }
    
    private void highlightCompletedText(int start) {
        editor.setCaretPosition(getLength());
        editor.moveCaretPosition(start);
    }
    
    private void setSelectedItem(Object item) {
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object lookupItem(String pattern) {
        Object selectedItem = model.getSelectedItem();
        // only search for a different item if the currently selected does not match
        if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
            return selectedItem;
        } else {
            // iterate over all items
            for (int i=0, n=model.getSize(); i < n; i++) {
                Object currentItem = model.getElementAt(i);
                // current item starts with the pattern?
                if (startsWithIgnoreCase(currentItem.toString(), pattern)) {
                    return currentItem;
                }
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    // checks if str1 starts with str2 - ignores case
    private boolean startsWithIgnoreCase(String str1, String str2) {
        return str1.toUpperCase().startsWith(str2.toUpperCase());
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // change the editor"s document
        new S17NonStrict(comboBox);
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Non-strict matching 2

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
This works, but has some inconveniences:
   1. The case-insensitive match makes it impossible to enter new items with correct case. Suppose you want to enter "EsTonto". Entering "E" will result in "Ester" being selected. You enter "s","T",... resulting in "Estonto". But you wanted an uppercase "T"...
   2. The backspace key should not only move the selection backwards when editing "new" items. Suppose you had entered "Esters" and you want to delete the trailing "s". Hitting backspace will highlight the "s" but won"t delete it.
The first issue can"t be resolved very easily. Each insert would be written to a protocoll and later the original string could be reconstructed (here"s the difficult part). I did a hack that is not really worth to be published but you can contact me, if you can"t live without this feature.
The second needed some coding. It won"t be explained here in more detail.

*/
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class S18NonStrictBackspace extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    JTextComponent editor;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    boolean hidePopupOnFocusLoss;
    boolean hitBackspace=false;
    boolean hitBackspaceOnSelection;
    boolean listContainsSelectedItem;
    
    public S18NonStrictBackspace(final JComboBox comboBox) {
        this.ruboBox = comboBox;
        model = comboBox.getModel();
        editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        editor.setDocument(this);
        comboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!selecting) highlightCompletedText(0);
            }
        });
        editor.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
                hitBackspace=false;
                switch (e.getKeyCode()) {
                    // determine if the pressed key is backspace (needed by the remove method)
                    case KeyEvent.VK_BACK_SPACE : hitBackspace=true;
                    hitBackspaceOnSelection=editor.getSelectionStart()!=editor.getSelectionEnd();
                    break;
                }
            }
        });
        // Bug 5100422 on Java 1.5: Editable JComboBox won"t hide popup when tabbing out
        hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5");
        // Highlight whole text when gaining focus
        editor.addFocusListener(new FocusAdapter() {
            public void focusGained(FocusEvent e) {
                highlightCompletedText(0);
            }
            public void focusLost(FocusEvent e) {
                // Workaround for Bug 5100422 - Hide Popup on focus loss
                if (hidePopupOnFocusLoss) comboBox.setPopupVisible(false);
            }
        });
        // Handle initially selected object
        Object selected = comboBox.getSelectedItem();
        if (selected!=null) setText(selected.toString());
        highlightCompletedText(0);
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        if (hitBackspace) {
            if (listContainsSelectedItem) {
                // move the selection backwards
                // old item keeps being selected
                if (offs>0) {
                    if (hitBackspaceOnSelection) offs--;
                } else {
                    // User hit backspace with the cursor positioned on the start => beep
                    comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
                }
                highlightCompletedText(offs);
                return;
            } else {
                super.remove(offs, len);
                String currentText = getText(0, getLength());
                // lookup if a matching item exists
                Object item = lookupItem(currentText);
                if (item != null) {
                    System.out.println(""" + item + "" matches.");
                    setSelectedItem(item);
                    listContainsSelectedItem=true;
                } else {
                    System.out.println("No match. Selecting "" + currentText + "".");
                    // no item matches => use the current input as selected item
                    item=currentText;
                    setSelectedItem(item);
                    listContainsSelectedItem=false;
                }
                // display the completed string
                String itemString=item.toString();
                setText(itemString);
                if (listContainsSelectedItem) highlightCompletedText(offs);
            }
        } else {
            super.remove(offs, len);
            setSelectedItem(getText(0, getLength()));
            listContainsSelectedItem=false;
        }
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        // insert the string into the document
        super.insertString(offs, str, a);
        // lookup and select a matching item
        Object item = lookupItem(getText(0, getLength()));
        
        listContainsSelectedItem = true;
        if (item == null) {
            // no item matches => use the current input as selected item
            item=getText(0, getLength());
            listContainsSelectedItem=false;
        }
        setSelectedItem(item);
        setText(item.toString());
        // select the completed part
        if (listContainsSelectedItem) highlightCompletedText(offs+str.length());
    }
    
    private void setText(String text) {
        try {
            // remove all text and insert the completed string
            super.remove(0, getLength());
            super.insertString(0, text, null);
        } catch (BadLocationException e) {
            throw new RuntimeException(e.toString());
        }
    }
    
    private void highlightCompletedText(int start) {
        editor.setCaretPosition(getLength());
        editor.moveCaretPosition(start);
    }
    
    private void setSelectedItem(Object item) {
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object lookupItem(String pattern) {
        Object selectedItem = model.getSelectedItem();
        // only search for a different item if the currently selected does not match
        if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern) && listContainsSelectedItem) {
            return selectedItem;
        } else {
            // iterate over all items
            for (int i=0, n=model.getSize(); i < n; i++) {
                Object currentItem = model.getElementAt(i);
                // current item starts with the pattern?
                if (startsWithIgnoreCase(currentItem.toString(), pattern)) {
                    return currentItem;
                }
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    // checks if str1 starts with str2 - ignores case
    private boolean startsWithIgnoreCase(String str1, String str2) {
        return str1.toUpperCase().startsWith(str2.toUpperCase());
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // change the editor"s document
        new S18NonStrictBackspace(comboBox);
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Popup the item list

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
Popup the item list when the user starts typing
One information that the user would like to have is the "neighbourhood" of the selected item (as has been described at the beginning). It would be nice to have the item list to popup when the user starts typing. The easiest solution is easy to add a KeyListener and call JComboBox.setPopupVisible whenever a keystroke is detected...
editor.addKeyListener(new KeyAdapter() {
  public void keyPressed(KeyEvent e) {
    if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
  }
});
Note that calls to setPopupVisible() might fail (IllegalComponentStateException) when the combo box is not visible. A check is done to prevent this from happening although a keystroke on the editor is unlikely to occur when the combo box is not visible ;-)

*/
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class S09ShowPopup extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    JTextComponent editor;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    
    public S09ShowPopup(final JComboBox comboBox) {
        this.ruboBox = comboBox;
        model = comboBox.getModel();
        editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        comboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!selecting) highlightCompletedText(0);
            }
        });
        editor.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
            }
        });
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        super.remove(offs, len);
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        // insert the string into the document
        super.insertString(offs, str, a);
        // lookup and select a matching item
        Object item = lookupItem(getText(0, getLength()));
        if (item != null) {
            setSelectedItem(item);
        } else {
            // keep old item selected if there is no match
            item = comboBox.getSelectedItem();
            // imitate no insert (later on offs will be incremented by str.length(): selection won"t move forward)
            offs = offs-str.length();
            // provide feedback to the user that his input has been received but can not be accepted
            comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
        }
        setText(item.toString());
        // select the completed part
        highlightCompletedText(offs+str.length());
    }
    
    private void setText(String text) throws BadLocationException {
        // remove all text and insert the completed string
        super.remove(0, getLength());
        super.insertString(0, text, null);
    }
    
    private void highlightCompletedText(int start) {
        editor.setSelectionStart(start);
        editor.setSelectionEnd(getLength());
    }
    
    private void setSelectedItem(Object item) {
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object lookupItem(String pattern) {
        Object selectedItem = model.getSelectedItem();
        // only search for a different item if the currently selected does not match
        if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
            return selectedItem;
        } else {
            // iterate over all items
            for (int i=0, n=model.getSize(); i < n; i++) {
                Object currentItem = model.getElementAt(i);
                // current item starts with the pattern?
                if (startsWithIgnoreCase(currentItem.toString(), pattern)) {
                    return currentItem;
                }
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    // checks if str1 starts with str2 - ignores case
    private boolean startsWithIgnoreCase(String str1, String str2) {
        return str1.toUpperCase().startsWith(str2.toUpperCase());
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // get the combo boxes editor component
        JTextComponent editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        // change the editor"s document
        editor.setDocument(new S09ShowPopup(comboBox));
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Prefer the currently selected item

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
Prefer the currently selected item
It"s not convincing from a user"s point of view, that the selected item might change although 
the entered letter fits the currently selected item (try it on your own: Select the item 
"Jordina" and hit "o" afterwards - "Jordi" gets selected). Another modification to the lookup 
mechanism...
*/
import javax.swing.*;
import javax.swing.text.*;
public class S06PreferSelected extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    JTextComponent editor;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    
    public S06PreferSelected(final JComboBox comboBox) {
        this.ruboBox = comboBox;
        model = comboBox.getModel();
        editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        super.remove(offs, len);
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        // insert the string into the document
        super.insertString(offs, str, a);
        // lookup and select a matching item
        Object item = lookupItem(getText(0, getLength()));
        setSelectedItem(item);
        setText(item.toString());
        // select the completed part
        highlightCompletedText(offs+str.length());
    }
    
    private void setText(String text) throws BadLocationException {
        // remove all text and insert the completed string
        super.remove(0, getLength());
        super.insertString(0, text, null);
    }
    
    private void highlightCompletedText(int start) {
        editor.setSelectionStart(start);
        editor.setSelectionEnd(getLength());
    }
    
    private void setSelectedItem(Object item) {
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object lookupItem(String pattern) {
        Object selectedItem = model.getSelectedItem();
        // only search for a different item if the currently selected does not match
        if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
            System.out.println("Selected item "" + selectedItem + "" matches "" + pattern + """);
            return selectedItem;
        } else {
            // iterate over all items
            for (int i=0, n=model.getSize(); i < n; i++) {
                Object currentItem = model.getElementAt(i);
                // current item starts with the pattern?
                if (startsWithIgnoreCase(currentItem.toString(), pattern)) {
                    System.out.println("New selection: "" + currentItem + """);
                    return currentItem;
                }
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    // checks if str1 starts with str2 - ignores case
    private boolean startsWithIgnoreCase(String str1, String str2) {
        return str1.toUpperCase().startsWith(str2.toUpperCase());
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // get the combo boxes editor component
        JTextComponent editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        // change the editor"s document
        editor.setDocument(new S06PreferSelected(comboBox));
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





JComboBox: adding automatic completion-Pressing backspace at the beginning

 
//Code from: http://www.orbital-computer.de/JComboBox/
/*
Inside JComboBox: adding automatic completion
Author: Thomas Bierhance
        thomas@orbital-computer.de
*/
/*
You might have noticed two remaining bugs: Pressing backspace at the beginning (e.g. when 
the complete text is highlighted) results in an IllegalArgumentException. Another 
inconvenience is that when the cursor is positioned on the end pressing backspace extends the 
selection to the last two characters not only to the last one. To solve this we also need to 
know if something was selected when the user hit backspace. Another variable to indicate this 
is introduced and the KeyListener and the remove method are modified accordingly. I also 
chose to ignore the deletion key...
editor.addKeyListener(new KeyAdapter() {
  public void keyPressed(KeyEvent e) {
    if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
    hitBackspace=false;
    switch (e.getKeyCode()) {
      // determine if the pressed key is backspace (needed by the remove method)
      case KeyEvent.VK_BACK_SPACE :
        hitBackspace=true;
        hitBackspaceOnSelection=editor.getSelectionStart()!=editor.getSelectionEnd();
        break;
      // ignore delete key
      case KeyEvent.VK_DELETE :
        e.consume();
        UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
        break;
    }
  }
});
public void remove(int offs, int len) throws BadLocationException {
  // return immediately when selecting an item
  if (selecting) return;
  if (hitBackspace) {
    // user hit backspace => move the selection backwards
    // old item keeps being selected
    if (offs>0) {
      if (hitBackspaceOnSelection) offs--;
    } else {
      // User hit backspace with the cursor positioned on the start => beep
      UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
    }
    highlightCompletedText(offs);
  } else {
    super.remove(offs, len);
  }
}
*/
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class S15WorkingBackspace extends PlainDocument {
    JComboBox comboBox;
    ComboBoxModel model;
    JTextComponent editor;
    // flag to indicate if setSelectedItem has been called
    // subsequent calls to remove/insertString should be ignored
    boolean selecting=false;
    boolean hidePopupOnFocusLoss;
    boolean hitBackspace=false;
    boolean hitBackspaceOnSelection;
    
    public S15WorkingBackspace(final JComboBox comboBox) {
        this.ruboBox = comboBox;
        model = comboBox.getModel();
        editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
        editor.setDocument(this);
        comboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!selecting) highlightCompletedText(0);
            }
        });
        editor.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (comboBox.isDisplayable()) comboBox.setPopupVisible(true);
                hitBackspace=false;
                switch (e.getKeyCode()) {
                    // determine if the pressed key is backspace (needed by the remove method)
                    case KeyEvent.VK_BACK_SPACE : hitBackspace=true;
                    hitBackspaceOnSelection=editor.getSelectionStart()!=editor.getSelectionEnd();
                    break;
                    // ignore delete key
                    case KeyEvent.VK_DELETE : e.consume();
                    comboBox.getToolkit().beep();
                    break;
                }
            }
        });
        // Bug 5100422 on Java 1.5: Editable JComboBox won"t hide popup when tabbing out
        hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5");
        // Highlight whole text when gaining focus
        editor.addFocusListener(new FocusAdapter() {
            public void focusGained(FocusEvent e) {
                highlightCompletedText(0);
            }
            public void focusLost(FocusEvent e) {
                // Workaround for Bug 5100422 - Hide Popup on focus loss
                if (hidePopupOnFocusLoss) comboBox.setPopupVisible(false);
            }
        });
        // Handle initially selected object
        Object selected = comboBox.getSelectedItem();
        if (selected!=null) setText(selected.toString());
        highlightCompletedText(0);
    }
    
    public void remove(int offs, int len) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        if (hitBackspace) {
            // user hit backspace => move the selection backwards
            // old item keeps being selected
            if (offs>0) {
                if (hitBackspaceOnSelection) offs--;
            } else {
                // User hit backspace with the cursor positioned on the start => beep
                comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
            }
            highlightCompletedText(offs);
        } else {
            super.remove(offs, len);
        }
    }
    
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        // return immediately when selecting an item
        if (selecting) return;
        // insert the string into the document
        super.insertString(offs, str, a);
        // lookup and select a matching item
        Object item = lookupItem(getText(0, getLength()));
        if (item != null) {
            setSelectedItem(item);
        } else {
            // keep old item selected if there is no match
            item = comboBox.getSelectedItem();
            // imitate no insert (later on offs will be incremented by str.length(): selection won"t move forward)
            offs = offs-str.length();
            // provide feedback to the user that his input has been received but can not be accepted
            comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
        }
        setText(item.toString());
        // select the completed part
        highlightCompletedText(offs+str.length());
    }
    
    private void setText(String text) {
        try {
            // remove all text and insert the completed string
            super.remove(0, getLength());
            super.insertString(0, text, null);
        } catch (BadLocationException e) {
            throw new RuntimeException(e.toString());
        }
    }
    
    private void highlightCompletedText(int start) {
        editor.setCaretPosition(getLength());
        editor.moveCaretPosition(start);
    }
    
    private void setSelectedItem(Object item) {
        selecting = true;
        model.setSelectedItem(item);
        selecting = false;
    }
    
    private Object lookupItem(String pattern) {
        Object selectedItem = model.getSelectedItem();
        // only search for a different item if the currently selected does not match
        if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
            return selectedItem;
        } else {
            // iterate over all items
            for (int i=0, n=model.getSize(); i < n; i++) {
                Object currentItem = model.getElementAt(i);
                // current item starts with the pattern?
                if (startsWithIgnoreCase(currentItem.toString(), pattern)) return currentItem;
            }
        }
        // no item starts with the pattern => return null
        return null;
    }
    
    // checks if str1 starts with str2 - ignores case
    private boolean startsWithIgnoreCase(String str1, String str2) {
        return str1.toUpperCase().startsWith(str2.toUpperCase());
    }
    
    private static void createAndShowGUI() {
        // the combo box (add/modify items if you like to)
        JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"});
        // has to be editable
        comboBox.setEditable(true);
        // change the editor"s document
        new S15WorkingBackspace(comboBox);
        
        // create and show a window containing the combo box
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(3);
        frame.getContentPane().add(comboBox);
        frame.pack(); frame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





MSN like Swing ComboBox

 
(From http://swinglabs.org/downloads.jsp)





Small Cell Combobox Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1) */

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Vector;
import javax.swing.ruboBoxModel;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.event.ListDataEvent;
import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.plaf.basic.ruboPopup;
import javax.swing.plaf.metal.MetalComboBoxUI;
import javax.swing.table.DefaultTableModel;
/**
 * @version 1.0 3/06/99
 */
public class SmallCellComboExample extends JFrame {
  public SmallCellComboExample() {
    super("SmallCell Combo Example");
    DefaultTableModel dm = new DefaultTableModel(4, 10) {
      public void setValueAt(Object obj, int row, int col) {
        if (obj != null) {
          String str;
          if (obj instanceof String) {
            str = ((String) obj).substring(0, 2);
          } else {
            str = obj.toString();
          }
          super.setValueAt(str, row, col);
        }
      }
    };
    JTable table = new JTable(dm);
    String[] str = { "010 - To Time", "020 - Vacation", "030 - Feel Bad" };
    SteppedComboBox combo = new SteppedComboBox(str) {
      public void contentsChanged(ListDataEvent e) {
        selectedItemReminder = null;
        super.contentsChanged(e);
      }
    };
    Dimension d = combo.getPreferredSize();
    combo.setPopupWidth(d.width);
    DefaultCellEditor editor = new DefaultCellEditor(combo);
    table.setDefaultEditor(Object.class, editor);
    JScrollPane scroll = new JScrollPane(table);
    getContentPane().add(scroll, BorderLayout.CENTER);
  }
  public static void main(String[] args) {
    SmallCellComboExample frame = new SmallCellComboExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.setSize(300, 120);
    frame.setVisible(true);
  }
}
/**
 * @version 1.0 12/12/98
 */
class SteppedComboBoxUI extends MetalComboBoxUI {
  protected ComboPopup createPopup() {
    BasicComboPopup popup = new BasicComboPopup(comboBox) {
      public void show() {
        Dimension popupSize = ((SteppedComboBox) comboBox)
            .getPopupSize();
        popupSize
            .setSize(popupSize.width,
                getPopupHeightForRowCount(comboBox
                    .getMaximumRowCount()));
        Rectangle popupBounds = computePopupBounds(0, comboBox
            .getBounds().height, popupSize.width, popupSize.height);
        scroller.setMaximumSize(popupBounds.getSize());
        scroller.setPreferredSize(popupBounds.getSize());
        scroller.setMinimumSize(popupBounds.getSize());
        list.invalidate();
        int selectedIndex = comboBox.getSelectedIndex();
        if (selectedIndex == -1) {
          list.clearSelection();
        } else {
          list.setSelectedIndex(selectedIndex);
        }
        list.ensureIndexIsVisible(list.getSelectedIndex());
        setLightWeightPopupEnabled(comboBox.isLightWeightPopupEnabled());
        show(comboBox, popupBounds.x, popupBounds.y);
      }
    };
    popup.getAccessibleContext().setAccessibleParent(comboBox);
    return popup;
  }
}
class SteppedComboBox extends JComboBox {
  protected int popupWidth;
  public SteppedComboBox(ComboBoxModel aModel) {
    super(aModel);
    setUI(new SteppedComboBoxUI());
    popupWidth = 0;
  }
  public SteppedComboBox(final Object[] items) {
    super(items);
    setUI(new SteppedComboBoxUI());
    popupWidth = 0;
  }
  public SteppedComboBox(Vector items) {
    super(items);
    setUI(new SteppedComboBoxUI());
    popupWidth = 0;
  }
  public void setPopupWidth(int width) {
    popupWidth = width;
  }
  public Dimension getPopupSize() {
    Dimension size = getSize();
    if (popupWidth < 1)
      popupWidth = size.width;
    return new Dimension(popupWidth, size.height);
  }
}





Stepped ComboBox Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1) */

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Vector;
import javax.swing.ruboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.plaf.basic.ruboPopup;
import javax.swing.plaf.metal.MetalComboBoxUI;
/**
 * @version 1.0 12/12/98
 */
public class SteppedComboBoxExample extends JFrame {
  public SteppedComboBoxExample() {
    super("SteppedComboBox Example");
    String[] str = { "A", "abcdefghijklmnopqrstuvwxyz",
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "0123456789" };
    SteppedComboBox combo = new SteppedComboBox(str);
    Dimension d = combo.getPreferredSize();
    combo.setPreferredSize(new Dimension(50, d.height));
    combo.setPopupWidth(d.width);
    getContentPane().setLayout(new FlowLayout());
    getContentPane().add(combo);
  }
  public static void main(String args[]) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    SteppedComboBoxExample f = new SteppedComboBoxExample();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    f.setSize(300, 100);
    f.show();
  }
}
class SteppedComboBoxUI extends MetalComboBoxUI {
  protected ComboPopup createPopup() {
    BasicComboPopup popup = new BasicComboPopup(comboBox) {
      public void show() {
        Dimension popupSize = ((SteppedComboBox) comboBox)
            .getPopupSize();
        popupSize
            .setSize(popupSize.width,
                getPopupHeightForRowCount(comboBox
                    .getMaximumRowCount()));
        Rectangle popupBounds = computePopupBounds(0, comboBox
            .getBounds().height, popupSize.width, popupSize.height);
        scroller.setMaximumSize(popupBounds.getSize());
        scroller.setPreferredSize(popupBounds.getSize());
        scroller.setMinimumSize(popupBounds.getSize());
        list.invalidate();
        int selectedIndex = comboBox.getSelectedIndex();
        if (selectedIndex == -1) {
          list.clearSelection();
        } else {
          list.setSelectedIndex(selectedIndex);
        }
        list.ensureIndexIsVisible(list.getSelectedIndex());
        setLightWeightPopupEnabled(comboBox.isLightWeightPopupEnabled());
        show(comboBox, popupBounds.x, popupBounds.y);
      }
    };
    popup.getAccessibleContext().setAccessibleParent(comboBox);
    return popup;
  }
}
class SteppedComboBox extends JComboBox {
  protected int popupWidth;
  public SteppedComboBox(ComboBoxModel aModel) {
    super(aModel);
    setUI(new SteppedComboBoxUI());
    popupWidth = 0;
  }
  public SteppedComboBox(final Object[] items) {
    super(items);
    setUI(new SteppedComboBoxUI());
    popupWidth = 0;
  }
  public SteppedComboBox(Vector items) {
    super(items);
    setUI(new SteppedComboBoxUI());
    popupWidth = 0;
  }
  public void setPopupWidth(int width) {
    popupWidth = width;
  }
  public Dimension getPopupSize() {
    Dimension size = getSize();
    if (popupWidth < 1)
      popupWidth = size.width;
    return new Dimension(popupWidth, size.height);
  }
}





Swing Auto Complete ComboBox

 
(From http://swinglabs.org/downloads.jsp)





The KeyedComboBox model allows to define an internal key (the data element) for every entry in the model.

  
/* 
 * JCommon : a free general purpose class library for the Java(tm) platform
 * 
 *
 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
 *
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
 * USA.
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
 * in the United States and other countries.]
 *
 * ------------------
 * KeyedComboBoxModel.java
 * ------------------
 * (C) Copyright 2004, by Thomas Morgner and Contributors.
 *
 * Original Author:  Thomas Morgner;
 * Contributor(s):   David Gilbert (for Object Refinery Limited);
 *
 * $Id: KeyedComboBoxModel.java,v 1.8 2008/09/10 09:26:11 mungady Exp $
 *
 * Changes
 * -------
 * 07-Jun-2004 : Added JCommon header (DG);
 *
 */
import java.util.ArrayList;
import javax.swing.ruboBoxModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
/**
 * The KeyedComboBox model allows to define an internal key (the data element)
 * for every entry in the model. <p/> This class is usefull in all cases, where
 * the public text differs from the internal view on the data. A separation
 * between presentation data and processing data is a prequesite for localizing
 * combobox entries. This model does not allow selected elements, which are not
 * in the list of valid elements.
 * 
 * @author Thomas Morgner
 */
public class KeyedComboBoxModel implements ComboBoxModel {
  /**
   * The internal data carrier to map keys to values and vice versa.
   */
  private static class ComboBoxItemPair {
    /**
     * The key.
     */
    private Object key;
    /**
     * The value for the key.
     */
    private Object value;
    /**
     * Creates a new item pair for the given key and value. The value can be
     * changed later, if needed.
     * 
     * @param key
     *          the key
     * @param value
     *          the value
     */
    public ComboBoxItemPair(final Object key, final Object value) {
      this.key = key;
      this.value = value;
    }
    /**
     * Returns the key.
     * 
     * @return the key.
     */
    public Object getKey() {
      return this.key;
    }
    /**
     * Returns the value.
     * 
     * @return the value for this key.
     */
    public Object getValue() {
      return this.value;
    }
    /**
     * Redefines the value stored for that key.
     * 
     * @param value
     *          the new value.
     */
    public void setValue(final Object value) {
      this.value = value;
    }
  }
  /**
   * The index of the selected item.
   */
  private int selectedItemIndex;
  private Object selectedItemValue;
  /**
   * The data (contains ComboBoxItemPairs).
   */
  private ArrayList data;
  /**
   * The listeners.
   */
  private ArrayList listdatalistener;
  /**
   * The cached listeners as array.
   */
  private transient ListDataListener[] tempListeners;
  private boolean allowOtherValue;
  /**
   * Creates a new keyed combobox model.
   */
  public KeyedComboBoxModel() {
    this.data = new ArrayList();
    this.listdatalistener = new ArrayList();
  }
  /**
   * Creates a new keyed combobox model for the given keys and values. Keys and
   * values must have the same number of items.
   * 
   * @param keys
   *          the keys
   * @param values
   *          the values
   */
  public KeyedComboBoxModel(final Object[] keys, final Object[] values) {
    this();
    setData(keys, values);
  }
  /**
   * Replaces the data in this combobox model. The number of keys must be equals
   * to the number of values.
   * 
   * @param keys
   *          the keys
   * @param values
   *          the values
   */
  public void setData(final Object[] keys, final Object[] values) {
    if (values.length != keys.length) {
      throw new IllegalArgumentException("Values and text must have the same length.");
    }
    this.data.clear();
    this.data.ensureCapacity(keys.length);
    for (int i = 0; i < values.length; i++) {
      add(keys[i], values[i]);
    }
    this.selectedItemIndex = -1;
    final ListDataEvent evt = new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, this.data
        .size() - 1);
    fireListDataEvent(evt);
  }
  /**
   * Notifies all registered list data listener of the given event.
   * 
   * @param evt
   *          the event.
   */
  protected synchronized void fireListDataEvent(final ListDataEvent evt) {
    if (this.tempListeners == null) {
      this.tempListeners = (ListDataListener[]) this.listdatalistener
          .toArray(new ListDataListener[this.listdatalistener.size()]);
    }
    final ListDataListener[] listeners = this.tempListeners;
    for (int i = 0; i < listeners.length; i++) {
      final ListDataListener l = listeners[i];
      l.contentsChanged(evt);
    }
  }
  /**
   * Returns the selected item.
   * 
   * @return The selected item or <code>null</code> if there is no selection
   */
  public Object getSelectedItem() {
    return this.selectedItemValue;
  }
  /**
   * Defines the selected key. If the object is not in the list of values, no
   * item gets selected.
   * 
   * @param anItem
   *          the new selected item.
   */
  public void setSelectedKey(final Object anItem) {
    if (anItem == null) {
      this.selectedItemIndex = -1;
      this.selectedItemValue = null;
    } else {
      final int newSelectedItem = findDataElementIndex(anItem);
      if (newSelectedItem == -1) {
        this.selectedItemIndex = -1;
        this.selectedItemValue = null;
      } else {
        this.selectedItemIndex = newSelectedItem;
        this.selectedItemValue = getElementAt(this.selectedItemIndex);
      }
    }
    fireListDataEvent(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, -1, -1));
  }
  /**
   * Set the selected item. The implementation of this method should notify all
   * registered <code>ListDataListener</code>s that the contents have
   * changed.
   * 
   * @param anItem
   *          the list object to select or <code>null</code> to clear the
   *          selection
   */
  public void setSelectedItem(final Object anItem) {
    if (anItem == null) {
      this.selectedItemIndex = -1;
      this.selectedItemValue = null;
    } else {
      final int newSelectedItem = findElementIndex(anItem);
      if (newSelectedItem == -1) {
        if (isAllowOtherValue()) {
          this.selectedItemIndex = -1;
          this.selectedItemValue = anItem;
        } else {
          this.selectedItemIndex = -1;
          this.selectedItemValue = null;
        }
      } else {
        this.selectedItemIndex = newSelectedItem;
        this.selectedItemValue = getElementAt(this.selectedItemIndex);
      }
    }
    fireListDataEvent(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, -1, -1));
  }
  private boolean isAllowOtherValue() {
    return this.allowOtherValue;
  }
  /**
   * @param allowOtherValue
   */
  public void setAllowOtherValue(final boolean allowOtherValue) {
    this.allowOtherValue = allowOtherValue;
  }
  /**
   * Adds a listener to the list that"s notified each time a change to the data
   * model occurs.
   * 
   * @param l
   *          the <code>ListDataListener</code> to be added
   */
  public synchronized void addListDataListener(final ListDataListener l) {
    if (l == null) {
      throw new NullPointerException();
    }
    this.listdatalistener.add(l);
    this.tempListeners = null;
  }
  /**
   * Returns the value at the specified index.
   * 
   * @param index
   *          the requested index
   * @return the value at <code>index</code>
   */
  public Object getElementAt(final int index) {
    if (index >= this.data.size()) {
      return null;
    }
    final ComboBoxItemPair datacon = (ComboBoxItemPair) this.data.get(index);
    if (datacon == null) {
      return null;
    }
    return datacon.getValue();
  }
  /**
   * Returns the key from the given index.
   * 
   * @param index
   *          the index of the key.
   * @return the the key at the specified index.
   */
  public Object getKeyAt(final int index) {
    if (index >= this.data.size()) {
      return null;
    }
    if (index < 0) {
      return null;
    }
    final ComboBoxItemPair datacon = (ComboBoxItemPair) this.data.get(index);
    if (datacon == null) {
      return null;
    }
    return datacon.getKey();
  }
  /**
   * Returns the selected data element or null if none is set.
   * 
   * @return the selected data element.
   */
  public Object getSelectedKey() {
    return getKeyAt(this.selectedItemIndex);
  }
  /**
   * Returns the length of the list.
   * 
   * @return the length of the list
   */
  public int getSize() {
    return this.data.size();
  }
  /**
   * Removes a listener from the list that"s notified each time a change to the
   * data model occurs.
   * 
   * @param l
   *          the <code>ListDataListener</code> to be removed
   */
  public void removeListDataListener(final ListDataListener l) {
    this.listdatalistener.remove(l);
    this.tempListeners = null;
  }
  /**
   * Searches an element by its data value. This method is called by the
   * setSelectedItem method and returns the first occurence of the element.
   * 
   * @param anItem
   *          the item
   * @return the index of the item or -1 if not found.
   */
  private int findDataElementIndex(final Object anItem) {
    if (anItem == null) {
      throw new NullPointerException("Item to find must not be null");
    }
    for (int i = 0; i < this.data.size(); i++) {
      final ComboBoxItemPair datacon = (ComboBoxItemPair) this.data.get(i);
      if (anItem.equals(datacon.getKey())) {
        return i;
      }
    }
    return -1;
  }
  /**
   * Tries to find the index of element with the given key. The key must not be
   * null.
   * 
   * @param key
   *          the key for the element to be searched.
   * @return the index of the key, or -1 if not found.
   */
  public int findElementIndex(final Object key) {
    if (key == null) {
      throw new NullPointerException("Item to find must not be null");
    }
    for (int i = 0; i < this.data.size(); i++) {
      final ComboBoxItemPair datacon = (ComboBoxItemPair) this.data.get(i);
      if (key.equals(datacon.getValue())) {
        return i;
      }
    }
    return -1;
  }
  /**
   * Removes an entry from the model.
   * 
   * @param key
   *          the key
   */
  public void removeDataElement(final Object key) {
    final int idx = findDataElementIndex(key);
    if (idx == -1) {
      return;
    }
    this.data.remove(idx);
    final ListDataEvent evt = new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, idx, idx);
    fireListDataEvent(evt);
  }
  /**
   * Adds a new entry to the model.
   * 
   * @param key
   *          the key
   * @param cbitem
   *          the display value.
   */
  public void add(final Object key, final Object cbitem) {
    final ComboBoxItemPair con = new ComboBoxItemPair(key, cbitem);
    this.data.add(con);
    final ListDataEvent evt = new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, this.data
        .size() - 2, this.data.size() - 2);
    fireListDataEvent(evt);
  }
  /**
   * Removes all entries from the model.
   */
  public void clear() {
    final int size = getSize();
    this.data.clear();
    final ListDataEvent evt = new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, 0, size - 1);
    fireListDataEvent(evt);
  }
}





ToolTip ComboBox Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1.1beta2) swing#1785 */
import java.awt.ruponent;
import java.awt.FlowLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
/**
 * @version 1.0 06/05/99
 */
public class ToolTipComboBoxExample extends JFrame {
  String[] items = { "jw", "ja", "la" };
  String[] tooltips = { "Javanese ", "Japanese ", "Latin " };
  public ToolTipComboBoxExample() {
    super("ToolTip ComboBox Example");
    JComboBox combo = new JComboBox(items);
    combo.setRenderer(new MyComboBoxRenderer());
    getContentPane().setLayout(new FlowLayout());
    getContentPane().add(combo);
  }
  class MyComboBoxRenderer extends BasicComboBoxRenderer {
    public Component getListCellRendererComponent(JList list, Object value,
        int index, boolean isSelected, boolean cellHasFocus) {
      if (isSelected) {
        setBackground(list.getSelectionBackground());
        setForeground(list.getSelectionForeground());
        if (-1 < index) {
          list.setToolTipText(tooltips[index]);
        }
      } else {
        setBackground(list.getBackground());
        setForeground(list.getForeground());
      }
      setFont(list.getFont());
      setText((value == null) ? "" : value.toString());
      return this;
    }
  }
  public static void main(String args[]) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    ToolTipComboBoxExample frame = new ToolTipComboBoxExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.setSize(200, 140);
    frame.setVisible(true);
  }
}