-
Notifications
You must be signed in to change notification settings - Fork 3
/
KeySelectionRenderer.java
148 lines (122 loc) · 3.5 KB
/
KeySelectionRenderer.java
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
/*
* This class can be used as the renderer and KeySelectionManager for an
* Object added to the ComboBoxModel.
*
* The class must be extended and the getDisplayValue() method must be
* implemented. This method will return a String to be rendered in the
* JComboBox. The same String will be used to do key selection of an
* item in the ComboBoxModel.
*/
abstract class KeySelectionRenderer extends BasicComboBoxRenderer
implements JComboBox.KeySelectionManager
{
// Used by the KeySelectionManager implementation to determine when to
// start a new search or append typed character to the existing search.
private long timeFactor;
private long lastTime;
private long time;
private String prefix = "";
public KeySelectionRenderer(JComboBox comboBox)
{
comboBox.setRenderer( this );
comboBox.setKeySelectionManager( this );
Long l = (Long)UIManager.get("ComboBox.timeFactor");
timeFactor = l == null ? 1000L : l.longValue();
}
/**
* This method must be implemented in the extended class.
*
* @param item an item from the ComboBoxModel
* @returns a String containing the text to be rendered for this item.
*/
public abstract String getDisplayValue(Object item);
// Implement the renderer
@Override
public Component getListCellRendererComponent(
JList list, Object item, int index, boolean isSelected, boolean hasFocus)
{
super.getListCellRendererComponent(list, item, index, isSelected, hasFocus);
if (item != null)
{
setText( getDisplayValue(item) );
}
return this;
}
// Implement the KeySelectionManager
@Override
public int selectionForKey(char aKey, ComboBoxModel model)
{
time = System.currentTimeMillis();
// Get the index of the currently selected item
int size = model.getSize();
int startIndex = -1;
Object selectedItem = model.getSelectedItem();
if (selectedItem != null)
{
for (int i = 0; i < size; i++)
{
if ( selectedItem == model.getElementAt(i) )
{
startIndex = i;
break;
}
}
}
// Determine the "prefix" to be used when searching the model. The
// prefix can be a single letter or multiple letters depending on how
// fast the user has been typing and on which letter has been typed.
if (time - lastTime < timeFactor)
{
if((prefix.length() == 1) && (aKey == prefix.charAt(0)))
{
// Subsequent same key presses move the keyboard focus to the next
// object that starts with the same letter.
startIndex++;
}
else
{
prefix += aKey;
}
}
else
{
startIndex++;
prefix = "" + aKey;
}
lastTime = time;
// Search from the current selection and wrap when no match is found
if (startIndex < 0 || startIndex >= size)
{
startIndex = 0;
}
int index = getNextMatch(prefix, startIndex, size, model);
if (index < 0)
{
// wrap
index = getNextMatch(prefix, 0, startIndex, model);
}
return index;
}
/*
** Find the index of the item in the model that starts with the prefix.
*/
private int getNextMatch(String prefix, int start, int end, ComboBoxModel model)
{
for (int i = start; i < end; i++ )
{
Object item = model.getElementAt(i);
if (item != null)
{
String displayValue = getDisplayValue( item ).toLowerCase();
if (displayValue.startsWith(prefix))
{
return i;
}
}
}
return -1;
}
}