/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.java.sip.communicator.impl.gui.customcontrols; import java.awt.*; import java.awt.event.*; import java.util.*; import java.util.List; import javax.swing.*; import javax.swing.event.*; import net.java.sip.communicator.plugin.desktoputil.plaf.*; import net.java.sip.communicator.util.skin.*; /** * <tt>SIPCommSmartComboBox</tt> is an editable combo box which selects an item * according to user input. * * @author Yana Stamcheva * @author Adam Netocny */ public class SIPCommSmartComboBox<E> extends JComboBox { private static final long serialVersionUID = 0L; /** * Creates an instance of <tt>SIPCommSmartComboBox</tt>. */ public SIPCommSmartComboBox() { setModel(new FilterableComboBoxModel()); setEditor(new CallComboEditor()); setEditable(true); setFocusable(true); } /** * The data model used for this combo box. Filters the contents of the * combo box popup according to the user input. */ public static class FilterableComboBoxModel extends AbstractListModel implements MutableComboBoxModel { private Filter filter; private final List<Object> filteredItems; private final List<Object> items; private Object selectedItem; public FilterableComboBoxModel() { items = new ArrayList<Object>(); filteredItems = new ArrayList<Object>(items.size()); updateFilteredItems(); } public boolean contains(Object obj) { return items.contains(obj); } public void addElement(Object obj) { items.add(obj); updateFilteredItems(); } public void removeElement(Object obj) { items.remove(obj); updateFilteredItems(); } public void removeElementAt(int index) { items.remove(index); updateFilteredItems(); } public void insertElementAt(Object obj, int index) { items.add(index, obj); updateFilteredItems(); } public void setFilter(Filter filter) { this.filter = filter; updateFilteredItems(); } protected void updateFilteredItems() { fireIntervalRemoved(this, 0, filteredItems.size()); filteredItems.clear(); if (filter == null) { filteredItems.addAll(items); } else { for (Object item : items) if (filter.accept(item)) filteredItems.add(item); } fireIntervalAdded(this, 0, filteredItems.size()); } public int getSize() { return filteredItems.size(); } public Object getElementAt(int index) { return filteredItems.get(index); } public Object getSelectedItem() { return selectedItem; } public void setSelectedItem(Object val) { if ((selectedItem == null) && (val == null)) return; if ((selectedItem != null) && selectedItem.equals(val)) return; if ((val != null) && val.equals(selectedItem)) return; selectedItem = val; fireContentsChanged(this, -1, -1); } } public static interface Filter { public boolean accept(Object obj); } private static class StartsWithFilter implements Filter { private final String prefix; public StartsWithFilter(String prefix) { this.prefix = prefix.toLowerCase(); } public boolean accept(Object o) { if(o != null) { String objectString = o.toString().toLowerCase(); return (objectString.indexOf(prefix) >= 0) ? true : false; } return false; } } public class CallComboEditor implements ComboBoxEditor, DocumentListener, Skinnable { private JTextField text; private volatile boolean filtering = false; private volatile boolean setting = false; public CallComboEditor() { text = new JTextField(15); text.getDocument().addDocumentListener(this); // Enable delete button from the UI. if (text.getUI() instanceof SIPCommTextFieldUI) { ((SIPCommTextFieldUI) text.getUI()) .setDeleteButtonEnabled(true); } } /** * Reloads UI if necessary. */ public void loadSkin() { if (text.getUI() instanceof SIPCommTextFieldUI) { ((SIPCommTextFieldUI) text.getUI()) .loadSkin(); } } public Component getEditorComponent() { return text; } public void setItem(Object item) { if (!filtering) { setting = true; try { text.setText((item == null) ? "" : item.toString()); } finally { setting = false; } } } public Object getItem() { return text.getText(); } public void selectAll() { text.selectAll(); } public void addActionListener(ActionListener l) { text.addActionListener(l); } public void removeActionListener(ActionListener l) { text.removeActionListener(l); } public void insertUpdate(DocumentEvent e) { handleChange(); } public void removeUpdate(DocumentEvent e) { handleChange(); } public void changedUpdate(DocumentEvent e) { } protected void handleChange() { if (setting) return; filtering = true; String prefix = text.getText(); Filter filter = (prefix.length() > 0) ? new StartsWithFilter(prefix) : null; ((FilterableComboBoxModel) getModel()).setFilter(filter); setPopupVisible(false); if(getModel().getSize() > 0) setPopupVisible(true); filtering = false; } } }