summaryrefslogtreecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/ComboBox.java
blob: cd2afbee960276336e936fbcfaf9fa409ff9490d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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<T> extends JComboBox<T> {

	/**
	 * Version for serialization.
	 */
	private static final long serialVersionUID = -114503880726655740L;

	public static abstract class ComboBoxRenderer<T> {
		public abstract String renderItem(T item);

		public String getEmptyText() {
			return null;
		}
	}

	private final Comparator<T> equalityComparator;
	private final ComboBoxRenderer<T> itemRenderer;
	private final ComboBox<T> me = this;
	private boolean replacedRenderer = false;
	private final Class<T> clazz;

	public ComboBox(ComboBoxRenderer<T> renderer, Class<T> clazz) {
		this(null, renderer, clazz);
	}

	public ComboBox(Comparator<T> equalityComparator, ComboBoxRenderer<T> renderer, Class<T> 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<T> 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<? super T> 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<T>() {
					@Override
					public Component getListCellRendererComponent(JList<? extends T> 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);
		}
	}

}