package org.openslx.dozmod.gui.control; import java.awt.Component; import java.util.Comparator; import javax.swing.ComboBoxModel; import javax.swing.DefaultListCellRenderer; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.ListCellRenderer; public class ComboBox extends JComboBox { /** * Version for serialization. */ private static final long serialVersionUID = -114503880726655740L; public static abstract class ComboBoxRenderer { public abstract String renderItem(T item); public String getEmptyText() { return null; } } private final Comparator equalityComparator; private final ComboBoxRenderer itemRenderer; private final ComboBox me = this; private boolean replacedRenderer = false; private final Class clazz; public ComboBox(ComboBoxRenderer renderer, Class clazz) { this(null, renderer, clazz); } public ComboBox(Comparator equalityComparator, ComboBoxRenderer renderer, Class clazz) { super(); this.clazz = clazz; this.itemRenderer = renderer; this.equalityComparator = equalityComparator; } /** * This version of {@link JComboBox#setSelectedItem(Object)} will use the * comparator given when constructing the ComboBox to determine if an entry * should be selected. */ @Override public void setSelectedItem(Object anObject) { if (anObject != null && equalityComparator != null) { ComboBoxModel model = getModel(); Object localObject = null; try { for (int i = 0; i < model.getSize(); ++i) { T element = model.getElementAt(i); if (equalityComparator.compare(this.clazz.cast(anObject), element) == 0) { localObject = element; break; } } super.setSelectedItem(localObject); return; } catch (ClassCastException e) { // Bummer, fall through } } super.setSelectedItem(anObject); } @Override public void updateUI() { super.updateUI(); if (!replacedRenderer) { replacedRenderer = true; final ListCellRenderer oldRenderer = super.getRenderer(); if (oldRenderer instanceof JLabel) { // The default JComboBox renderer always seems to be a subclass of JLabel, which is nice ((JLabel) oldRenderer).putClientProperty("html.disable", Boolean.TRUE); ((JLabel) oldRenderer).putClientProperty("html", null); super.setRenderer(new ListCellRenderer() { @Override public Component getListCellRendererComponent(JList list, T value, int index, boolean isSelected, boolean cellHasFocus) { String text; if (me.getModel().getSize() == 0) { text = itemRenderer.getEmptyText(); } else { text = itemRenderer.renderItem(value); } Component comp = oldRenderer.getListCellRendererComponent(list, null, index, isSelected, cellHasFocus); comp.setEnabled(me.isEnabled()); ((JLabel) comp).setText(text); return comp; } }); } else { // Fallback, in case there's any platform, L&F, runtime environment or whatnot where it's not a JLabel super.setRenderer(new FallbackCellRenderer()); } } } private class FallbackCellRenderer extends DefaultListCellRenderer { /** * Version for serialization. */ private static final long serialVersionUID = 3441233718432775129L; public FallbackCellRenderer() { putClientProperty("html.disable", Boolean.TRUE); putClientProperty("html", null); } @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { if (me.getModel().getSize() == 0) { value = itemRenderer.getEmptyText(); } else { try { value = itemRenderer.renderItem(ComboBox.this.clazz.cast(value)); } catch (ClassCastException e) { // Should never happen; do nothing, retain original value } } return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); } } }