1
|
|
package abbot.editor.widgets;
|
2
|
|
|
3
|
|
import java.awt.*;
|
4
|
|
import java.awt.event.*;
|
5
|
|
import javax.swing.*;
|
6
|
|
import javax.swing.border.*;
|
7
|
|
import javax.swing.event.*;
|
8
|
|
import javax.swing.text.*;
|
9
|
|
import java.util.*;
|
10
|
|
import java.net.*;
|
11
|
|
|
12
|
|
import abbot.Log;
|
13
|
|
import abbot.i18n.Strings;
|
14
|
|
import abbot.editor.widgets.TextField;
|
15
|
|
|
16
|
|
|
17
|
|
|
18
|
|
|
19
|
|
|
20
|
|
|
21
|
|
|
22
|
|
|
23
|
|
|
24
|
|
|
25
|
|
public class ArrayEditor extends Box {
|
26
|
|
|
27
|
|
public static final String ACTION_LIST_CHANGED = "list.changed";
|
28
|
|
public static final String ACTION_ITEM_CHANGED = "item.changed";
|
29
|
|
public static final String ACTION_ITEM_INSERTED = "item.inserted";
|
30
|
|
public static final String ACTION_ITEM_DELETED = "item.deleted";
|
31
|
|
|
32
|
|
private static final int DEFAULT_COLUMNS = 10;
|
33
|
|
private ArrayList listeners = new ArrayList();
|
34
|
|
private ArrayList data;
|
35
|
|
private boolean adjusting = false;
|
36
|
|
private ArrayList rows = new ArrayList();
|
37
|
|
|
38
|
|
protected interface ElementEditor {
|
39
|
|
void setValue(Object value);
|
40
|
|
Object getValue();
|
41
|
|
Component getEditorComponent();
|
42
|
|
void addActionListener(ActionListener listener);
|
43
|
|
void removeActionListener(ActionListener listener);
|
44
|
|
void setEnabled(boolean enabled);
|
45
|
|
}
|
46
|
|
|
47
|
|
|
48
|
|
protected class TextEditor extends TextField implements ElementEditor {
|
49
|
59
|
public TextEditor(Object value) {
|
50
|
59
|
super(value.toString(), DEFAULT_COLUMNS);
|
51
|
|
}
|
52
|
49
|
public Object getValue() { return getText(); }
|
53
|
5
|
public void setValue(Object o) {
|
54
|
5
|
setText(o == null ? "" : o.toString());
|
55
|
|
}
|
56
|
59
|
public Component getEditorComponent() {
|
57
|
59
|
return this;
|
58
|
|
}
|
59
|
|
}
|
60
|
|
|
61
|
|
|
62
|
|
|
63
|
|
|
64
|
|
protected class Row extends JPanel {
|
65
|
|
public ElementEditor elementEditor;
|
66
|
|
public Component editor;
|
67
|
|
public JButton addButton;
|
68
|
|
public JButton removeButton;
|
69
|
|
|
70
|
|
private class SizedButton extends JButton {
|
71
|
118
|
public SizedButton(String label) {
|
72
|
118
|
super(label);
|
73
|
|
}
|
74
|
|
|
75
|
195
|
public Insets getInsets() {
|
76
|
195
|
Insets insets = super.getInsets();
|
77
|
195
|
int min = Math.min(insets.top,
|
78
|
|
Math.min(insets.bottom,
|
79
|
|
Math.min(insets.right,
|
80
|
|
insets.left)));
|
81
|
195
|
insets.right = insets.left = insets.top = insets.bottom = min;
|
82
|
195
|
return insets;
|
83
|
|
}
|
84
|
230
|
public Dimension getMinimumSize() {
|
85
|
230
|
return getPreferredSize();
|
86
|
|
}
|
87
|
230
|
public Dimension getMaximumSize() {
|
88
|
230
|
return getPreferredSize();
|
89
|
|
}
|
90
|
690
|
public Dimension getPreferredSize() {
|
91
|
690
|
Dimension size = editor.getPreferredSize();
|
92
|
690
|
size.width = size.height;
|
93
|
690
|
return size;
|
94
|
|
}
|
95
|
|
}
|
96
|
|
|
97
|
59
|
public Row(Object value) {
|
98
|
59
|
BorderLayout layout = new BorderLayout();
|
99
|
59
|
layout.setVgap(0);
|
100
|
59
|
setLayout(layout);
|
101
|
59
|
elementEditor = createEditor(value);
|
102
|
59
|
add(editor = elementEditor.getEditorComponent());
|
103
|
59
|
editor.setName("editor");
|
104
|
59
|
Box buttons = new Box(BoxLayout.X_AXIS);
|
105
|
59
|
add(buttons, BorderLayout.EAST);
|
106
|
59
|
buttons.add(removeButton = new SizedButton("-"));
|
107
|
59
|
removeButton.setName("remove");
|
108
|
59
|
removeButton.setToolTipText(Strings.get("editor.array.remove"));
|
109
|
59
|
buttons.add(addButton = new SizedButton("+"));
|
110
|
59
|
addButton.setName("add");
|
111
|
59
|
addButton.setToolTipText(Strings.get("editor.array.insert"));
|
112
|
|
|
113
|
59
|
addButton.addActionListener(new ActionListener() {
|
114
|
3
|
public void actionPerformed(ActionEvent e) {
|
115
|
3
|
insertRow(getRowCount() == 0
|
116
|
|
? 0 : getRowIndex() + 1);
|
117
|
|
}
|
118
|
|
});
|
119
|
59
|
removeButton.addActionListener(new ActionListener() {
|
120
|
2
|
public void actionPerformed(ActionEvent e) {
|
121
|
2
|
removeRow(getRowIndex());
|
122
|
|
}
|
123
|
|
});
|
124
|
59
|
elementEditor.addActionListener(new ActionListener() {
|
125
|
50
|
public void actionPerformed(ActionEvent e) {
|
126
|
50
|
int index = getRowIndex();
|
127
|
50
|
if (!adjusting && index != -1) {
|
128
|
49
|
adjusting = true;
|
129
|
49
|
setValueAt(index, elementEditor.getValue(), true);
|
130
|
49
|
adjusting = false;
|
131
|
|
}
|
132
|
|
}
|
133
|
|
});
|
134
|
|
}
|
135
|
|
|
136
|
84
|
public Dimension getMaximumSize() {
|
137
|
84
|
Dimension size = super.getMaximumSize();
|
138
|
84
|
size.height = super.getPreferredSize().height;
|
139
|
84
|
return size;
|
140
|
|
}
|
141
|
|
|
142
|
54
|
protected int getRowIndex() {
|
143
|
54
|
Container parent = getParent();
|
144
|
54
|
if (parent != null) {
|
145
|
54
|
Component kids[] = parent.getComponents();
|
146
|
59
|
for (int i=0;i < kids.length;i++) {
|
147
|
59
|
if (kids[i] == this) {
|
148
|
54
|
return i;
|
149
|
|
}
|
150
|
|
}
|
151
|
|
}
|
152
|
0
|
return -1;
|
153
|
|
}
|
154
|
|
|
155
|
0
|
public String toString() {
|
156
|
0
|
return super.toString()
|
157
|
|
+ "[" + getRowIndex() + ": " + elementEditor.getValue() + "]";
|
158
|
|
}
|
159
|
|
}
|
160
|
|
|
161
|
|
|
162
|
4
|
public ArrayEditor() {
|
163
|
4
|
this(new String[0]);
|
164
|
|
}
|
165
|
|
|
166
|
|
|
167
|
34
|
public ArrayEditor(Object[] contents) {
|
168
|
34
|
super(BoxLayout.Y_AXIS);
|
169
|
34
|
setValues(contents, false);
|
170
|
|
}
|
171
|
|
|
172
|
59
|
protected ElementEditor createEditor(Object initialValue) {
|
173
|
59
|
return new TextEditor(initialValue);
|
174
|
|
}
|
175
|
|
|
176
|
11
|
private Row getRow(int row) {
|
177
|
11
|
return (Row)rows.get(row);
|
178
|
|
}
|
179
|
|
|
180
|
59
|
private Row addRow(int index, Object value) {
|
181
|
59
|
Row row = new Row(value);
|
182
|
59
|
rows.add(index, row);
|
183
|
59
|
add(row, index);
|
184
|
59
|
return row;
|
185
|
|
}
|
186
|
|
|
187
|
41
|
private void init() {
|
188
|
41
|
removeAll();
|
189
|
41
|
rows.clear();
|
190
|
41
|
for (int i=0;i < data.size();i++) {
|
191
|
29
|
addRow(i, data.get(i));
|
192
|
|
}
|
193
|
|
|
194
|
41
|
if (data.size() == 0) {
|
195
|
24
|
Row row = addRow(0, "");
|
196
|
24
|
row.removeButton.setEnabled(false);
|
197
|
24
|
row.elementEditor.setEnabled(false);
|
198
|
|
}
|
199
|
41
|
validate();
|
200
|
41
|
repaint();
|
201
|
|
}
|
202
|
|
|
203
|
42
|
private void setValues(Object[] contents, boolean fire) {
|
204
|
42
|
if (contents == null) {
|
205
|
0
|
if (data != null) {
|
206
|
0
|
data = null;
|
207
|
0
|
init();
|
208
|
0
|
if (fire)
|
209
|
0
|
fireActionPerformed(ACTION_LIST_CHANGED, -1);
|
210
|
|
}
|
211
|
|
}
|
212
|
42
|
else if (data == null || contents.length != data.size()) {
|
213
|
41
|
data = new ArrayList(Arrays.asList(contents));
|
214
|
41
|
init();
|
215
|
41
|
if (fire)
|
216
|
7
|
fireActionPerformed(ACTION_LIST_CHANGED, -1);
|
217
|
|
}
|
218
|
|
else {
|
219
|
1
|
for (int i=0;i < contents.length;i++) {
|
220
|
0
|
setValueAt(i, contents[i], fire);
|
221
|
|
}
|
222
|
|
}
|
223
|
|
}
|
224
|
|
|
225
|
34
|
public int getRowCount() {
|
226
|
34
|
return data.size();
|
227
|
|
}
|
228
|
|
|
229
|
4
|
public void insertRow(int row) {
|
230
|
4
|
insertRow(row, "");
|
231
|
|
}
|
232
|
|
|
233
|
9
|
public void insertRow(int row, Object value) {
|
234
|
9
|
if (row < 0 || row > data.size())
|
235
|
1
|
row = data.size();
|
236
|
9
|
data.add(row, value);
|
237
|
9
|
if (data.size() == 1) {
|
238
|
3
|
row = 0;
|
239
|
3
|
Row r = getRow(row);
|
240
|
3
|
r.elementEditor.setEnabled(true);
|
241
|
3
|
r.removeButton.setEnabled(true);
|
242
|
3
|
r.elementEditor.setValue(value);
|
243
|
|
}
|
244
|
|
else {
|
245
|
6
|
addRow(row, value);
|
246
|
|
}
|
247
|
9
|
validate();
|
248
|
9
|
repaint();
|
249
|
9
|
fireActionPerformed(ACTION_ITEM_INSERTED, row);
|
250
|
|
}
|
251
|
|
|
252
|
8
|
public void removeRow(int index) {
|
253
|
8
|
if (index < 0 || index >= getRowCount())
|
254
|
1
|
throw new IllegalArgumentException("Row " + index
|
255
|
|
+ " out of bounds ("
|
256
|
|
+ getRowCount() + ")");
|
257
|
7
|
Row r = getRow(index);
|
258
|
7
|
data.remove(index);
|
259
|
|
|
260
|
7
|
if (data.size() == 0) {
|
261
|
|
|
262
|
1
|
adjusting = true;
|
263
|
1
|
r.elementEditor.setValue(null);
|
264
|
1
|
adjusting = false;
|
265
|
1
|
r.elementEditor.setEnabled(false);
|
266
|
1
|
r.removeButton.setEnabled(false);
|
267
|
|
}
|
268
|
|
else {
|
269
|
6
|
rows.remove(r);
|
270
|
6
|
remove(r);
|
271
|
|
}
|
272
|
7
|
validate();
|
273
|
7
|
repaint();
|
274
|
7
|
fireActionPerformed(ACTION_ITEM_DELETED, index);
|
275
|
|
}
|
276
|
|
|
277
|
56
|
public Object[] getValues() {
|
278
|
56
|
return data.toArray(new Object[data.size()]);
|
279
|
|
}
|
280
|
|
|
281
|
8
|
public void setValues(Object[] contents) {
|
282
|
8
|
setValues(contents, true);
|
283
|
|
}
|
284
|
|
|
285
|
1
|
public void setValueAt(int index, Object value) {
|
286
|
1
|
setValueAt(index, value, true);
|
287
|
|
}
|
288
|
|
|
289
|
50
|
private void setValueAt(int index, Object value, boolean fire) {
|
290
|
50
|
if (index < 0 || index >= data.size())
|
291
|
0
|
throw new IndexOutOfBoundsException("Index " + index
|
292
|
|
+ " out of range ("
|
293
|
|
+ data.size() + ")");
|
294
|
50
|
if (value == data.get(index)
|
295
|
|
|| (value != null && value.equals(data.get(index))))
|
296
|
4
|
return;
|
297
|
|
|
298
|
46
|
data.set(index, value);
|
299
|
46
|
if (!adjusting)
|
300
|
1
|
getRow(index).elementEditor.setValue(value);
|
301
|
46
|
if (fire)
|
302
|
46
|
fireActionPerformed(ACTION_ITEM_CHANGED, index);
|
303
|
|
}
|
304
|
|
|
305
|
20
|
public String getValueAt(int index) {
|
306
|
20
|
return (String)data.get(index);
|
307
|
|
}
|
308
|
|
|
309
|
69
|
protected void fireActionPerformed(String action, int index) {
|
310
|
69
|
Iterator iter = listeners.iterator();
|
311
|
69
|
ActionEvent e = new ActionEvent(this, index, action);
|
312
|
69
|
while (iter.hasNext()) {
|
313
|
100
|
((ActionListener)iter.next()).actionPerformed(e);
|
314
|
|
}
|
315
|
|
}
|
316
|
|
|
317
|
55
|
public void addActionListener(ActionListener l) {
|
318
|
55
|
listeners.add(l);
|
319
|
|
}
|
320
|
|
|
321
|
0
|
public void removeActionListener(ActionListener l) {
|
322
|
0
|
listeners.remove(l);
|
323
|
|
}
|
324
|
|
}
|
325
|
|
|