All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.widget.JComboBoxAutoCompletionKit Maven / Gradle / Ivy

There is a newer version: 1.1.1
Show newest version
/* *##% Graphical Widget
 * Copyright (C) 2004 - 2008 CodeLutin
 *
 * This program 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 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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 General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * . ##%*/

/* *
 * JComboBoxAutoCompletionKit.java
 *
 * Created: Nov 12, 2004
 *
 * @author Cédric Pineau 
 * @version $Revision: 254 $
 *
 * Last update : $Date: 2010-04-10 01:13:11 +0200 (sam., 10 avril 2010) $
 * by : $Author: tchemit $
 */

package org.nuiton.widget;

import java.awt.Component;

import javax.swing.ComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;

/**
 *  
 */
public class JComboBoxAutoCompletionKit {

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        String[] petStrings = { "Bird", "Cat", "Cot", "Dog", "Dog", "Dog1",
                "Dog2", "Dog3", "Dog4", "Dog5", "Dog6", "Dog7", "Dog", "Dog8",
                "Dog9", "Dog10", "Rabbit", "Pig" };
        JComboBox combo = new JComboBox(petStrings);
        combo.setRenderer(new TestCellRenderer());
        JComboBoxAutoCompletionKit.setAutoCompleted(combo);
        frame.getContentPane().add(combo);
        frame.setSize(800, 50);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public static void setAutoCompleted(JComboBox comboBox) {
        AutoCompletionManager autoCompletionManager = new AutoCompletionManager(
                comboBox);
        AutoCompletionModelListener autoCompletionModelListener = new AutoCompletionModelListener(
                autoCompletionManager);
        AutoCompletionCellRenderer autoCompletionCellRenderer = new AutoCompletionCellRenderer(
                autoCompletionManager, comboBox.getRenderer());
        comboBox.setKeySelectionManager(autoCompletionManager);
        comboBox.getModel().addListDataListener(autoCompletionModelListener);
        comboBox.setRenderer(autoCompletionCellRenderer);
    }

    private static class AutoCompletionManager implements
            JComboBox.KeySelectionManager {

        private static String EMPTY_PREFIX = "";

        private static int NO_SELECTION = -1;

        private JComboBox _comboBox = null;

        private int _currentSelection = NO_SELECTION;

        private String _prefix = EMPTY_PREFIX;

        public AutoCompletionManager(JComboBox comboBox) {
            setComboBox(comboBox);
        }

        @Override
        public int selectionForKey(char key, ComboBoxModel model) {
            // TODO change allowed chars to include *, -, ...
            System.out.println("" + Integer.toString(key)); // TODO remove this
            if (((key == 8) && (getPrefix().length() > 0))
                    || (Character.isLetterOrDigit(key))) {

                // Build the new prefix and set it
                String prefix = getPrefix();
                if ((key == 8) && (prefix.length() > 0)) {
                    prefix = prefix.substring(0, prefix.length() - 1);
                } else {
                    prefix = getPrefix() + key;
                }
                setPrefix(prefix);

                // Look for the first model item with given prefix
                boolean prefixedItemFound = false;
                for (int i = 0; i < model.getSize(); i++) {
                    Object element = model.getElementAt(i);
                    if (element.toString().startsWith(prefix)) {
                        // Found it, this is the newly selected item
                        setCurrentSelection(i);
                        prefixedItemFound = true;
                        break;
                    }
                }

                // Reset AutoCompletion if prefix can't be found
                if (!prefixedItemFound) {
                    reset();
                }
                // Ensure popup is shown
                getComboBox().showPopup();
                // Force a repaint
                model.setSelectedItem(null);
            }

            return getCurrentSelection();
        }

        public void reset() {
            setPrefix(EMPTY_PREFIX);
            setCurrentSelection(NO_SELECTION);
        }

        /**
         * Called by the model listener when model has changed.
         */
        public void modelChanged() {
            // reset();
        }

        protected JComboBox getComboBox() {
            return _comboBox;
        }

        protected void setComboBox(JComboBox comboBox) {
            _comboBox = comboBox;
        }

        protected int getCurrentSelection() {
            return _currentSelection;
        }

        protected void setCurrentSelection(int currentSelection) {
            _currentSelection = currentSelection;
        }

        protected String getPrefix() {
            return _prefix;
        }

        protected void setPrefix(String prefix) {
            this._prefix = prefix;
        }
    }

    private static class TestCellRenderer extends DefaultListCellRenderer {

        private static final long serialVersionUID = 1L;

        @Override
        public Component getListCellRendererComponent(JList list, Object value,
                int index, boolean isSelected, boolean cellHasFocus) {
            // Ask to default renderer to do the job for us
            Component component = super.getListCellRendererComponent(list,
                    value, index, isSelected, cellHasFocus);

            if (value != null) {
                // Can we trick the rendered thing to reflect current prefix ?
                if (component instanceof JLabel) {
                    // Everything's fine. Let's have a closer look.
                    JLabel label = (JLabel) component;
                    String text = label.getText();
                    text = "J" + text;
                    label.setText(text);
                }
            }

            return component;
        }

    }

    private static class AutoCompletionCellRenderer extends
            DefaultListCellRenderer {

        private static final long serialVersionUID = 1L;
        
        private ListCellRenderer _existingRenderer = null;
        private AutoCompletionManager _manager = null;

        public AutoCompletionCellRenderer(AutoCompletionManager manager,
                ListCellRenderer existingRenderer) {
            setManager(manager);
            setExistingRenderer(existingRenderer);
        }

        @Override
        public Component getListCellRendererComponent(JList list, Object value,
                int index, boolean isSelected, boolean cellHasFocus) {
            // Ask to default renderer to do the job for us
            Component component = getExistingRenderer()
                    .getListCellRendererComponent(list, value, index,
                            isSelected, cellHasFocus);

            if (value != null) {
                // Can we trick the rendered thing to reflect current prefix ?
                String prefix = getManager().getPrefix();
                if ((prefix != null) && (component instanceof JLabel)) {
                    // Everything's fine. Let's have a closer look.
                    JLabel label = (JLabel) component;
                    if (value.toString().startsWith(prefix)) {
                        // We're going trick the label a little bit
                        String text = label.getText();
                        text = "" + prefix
                                + "" + text.substring(prefix.length())
                                + "";
                        label.setText(text);
                    }
                }
            }

            return component;
        }

        protected AutoCompletionManager getManager() {
            return this._manager;
        }

        protected void setManager(AutoCompletionManager manager) {
            this._manager = manager;
        }

        /**
         * @return Returns the _existingRenderer.
         */
        protected ListCellRenderer getExistingRenderer() {
            return this._existingRenderer;
        }

        /**
         * @param renderer The _existingRenderer to set.
         */
        protected void setExistingRenderer(ListCellRenderer existingRenderer) {
            this._existingRenderer = existingRenderer;
        }
    }

    private static class AutoCompletionModelListener implements
            ListDataListener {

        private AutoCompletionManager _manager = null;

        public AutoCompletionModelListener(AutoCompletionManager manager) {
            setManager(manager);
        }

        @Override
        public void intervalAdded(ListDataEvent e) {
            // To be optimized...
            getManager().modelChanged();
        }

        @Override
        public void intervalRemoved(ListDataEvent e) {
            // To be optimized...
            getManager().modelChanged();
        }

        @Override
        public void contentsChanged(ListDataEvent e) {
            // To be optimized...
            getManager().modelChanged();
        }

        protected AutoCompletionManager getManager() {
            return _manager;
        }

        protected void setManager(AutoCompletionManager manager) {
            this._manager = manager;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy