1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package p3j.gui.panels.matrices;
17
18 import james.SimSystem;
19
20 import java.awt.Toolkit;
21 import java.awt.datatransfer.Clipboard;
22 import java.awt.datatransfer.DataFlavor;
23 import java.awt.datatransfer.StringSelection;
24 import java.awt.event.ActionEvent;
25 import java.awt.event.ActionListener;
26 import java.awt.event.KeyEvent;
27 import java.util.StringTokenizer;
28 import java.util.logging.Level;
29
30 import javax.swing.JComponent;
31 import javax.swing.KeyStroke;
32
33 import net.sf.jeppers.grid.JGrid;
34 import net.sf.jeppers.grid.SelectionModel;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public class GridBehaviourAdapter implements ActionListener {
52
53
54 public static final String ACTION_COMMAND_RIGHT = "Right";
55
56
57 public static final String ACTION_COMMAND_LEFT = "Left";
58
59
60 public static final String ACTION_COMMAND_UP = "Up";
61
62
63 public static final String ACTION_COMMAND_DOWN = "Down";
64
65
66 public static final String FAST_PREFIX = "fast";
67
68
69 public static final String FAST_SELECTION_CMD_PREFIX = "fastSel";
70
71
72 private JGrid grid;
73
74
75 private SelectionModel selModel;
76
77
78 private Clipboard clipBoard;
79
80
81
82
83 public static final int DIR_UP = 0;
84
85
86 public static final int DIR_RIGHT = 1;
87
88
89 public static final int DIR_DOWN = 2;
90
91
92 public static final int DIR_LEFT = 3;
93
94
95
96
97
98
99 public static KeyStroke getCopyKeyStroke() {
100 return KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK, false);
101 }
102
103
104
105
106
107
108 public static KeyStroke getCutKeyStroke() {
109 return KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.CTRL_MASK, false);
110 }
111
112
113
114
115
116
117 public static KeyStroke getPasteKeyStroke() {
118 return KeyStroke.getKeyStroke(KeyEvent.VK_V, ActionEvent.CTRL_MASK, false);
119 }
120
121
122
123
124
125
126
127 public GridBehaviourAdapter(JGrid target) {
128
129 this.grid = target;
130 this.selModel = target.getSelectionModel();
131 clipBoard = Toolkit.getDefaultToolkit().getSystemClipboard();
132
133 KeyStroke cut = getCutKeyStroke();
134 KeyStroke copy = getCopyKeyStroke();
135 KeyStroke paste = getPasteKeyStroke();
136
137 KeyStroke delete = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0, false);
138
139 KeyStroke fastUp = KeyStroke.getKeyStroke(KeyEvent.VK_UP,
140 ActionEvent.CTRL_MASK, false);
141 KeyStroke fastDown = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,
142 ActionEvent.CTRL_MASK, false);
143 KeyStroke fastLeft = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,
144 ActionEvent.CTRL_MASK, false);
145 KeyStroke fastRight = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,
146 ActionEvent.CTRL_MASK, false);
147
148 KeyStroke fastSelUp = KeyStroke.getKeyStroke(KeyEvent.VK_UP,
149 ActionEvent.CTRL_MASK | ActionEvent.SHIFT_MASK, false);
150 KeyStroke fastSelDown = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,
151 ActionEvent.CTRL_MASK | ActionEvent.SHIFT_MASK, false);
152 KeyStroke fastSelLeft = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,
153 ActionEvent.CTRL_MASK | ActionEvent.SHIFT_MASK, false);
154 KeyStroke fastSelRight = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,
155 ActionEvent.CTRL_MASK | ActionEvent.SHIFT_MASK, false);
156
157 target.registerKeyboardAction(this, "Cut", cut, JComponent.WHEN_FOCUSED);
158 target.registerKeyboardAction(this, "Copy", copy, JComponent.WHEN_FOCUSED);
159 target
160 .registerKeyboardAction(this, "Paste", paste, JComponent.WHEN_FOCUSED);
161 target.registerKeyboardAction(this, "Delete", delete,
162 JComponent.WHEN_FOCUSED);
163 target.registerKeyboardAction(this, FAST_PREFIX + ACTION_COMMAND_UP,
164 fastUp, JComponent.WHEN_FOCUSED);
165 target.registerKeyboardAction(this, FAST_PREFIX + ACTION_COMMAND_DOWN,
166 fastDown, JComponent.WHEN_FOCUSED);
167 target.registerKeyboardAction(this, FAST_PREFIX + ACTION_COMMAND_LEFT,
168 fastLeft, JComponent.WHEN_FOCUSED);
169 target.registerKeyboardAction(this, FAST_PREFIX + ACTION_COMMAND_RIGHT,
170 fastRight, JComponent.WHEN_FOCUSED);
171 target.registerKeyboardAction(this, FAST_SELECTION_CMD_PREFIX
172 + ACTION_COMMAND_UP, fastSelUp, JComponent.WHEN_FOCUSED);
173 target.registerKeyboardAction(this, FAST_SELECTION_CMD_PREFIX
174 + ACTION_COMMAND_DOWN, fastSelDown, JComponent.WHEN_FOCUSED);
175 target.registerKeyboardAction(this, FAST_SELECTION_CMD_PREFIX
176 + ACTION_COMMAND_LEFT, fastSelLeft, JComponent.WHEN_FOCUSED);
177 target.registerKeyboardAction(this, FAST_SELECTION_CMD_PREFIX
178 + ACTION_COMMAND_RIGHT, fastSelRight, JComponent.WHEN_FOCUSED);
179
180 }
181
182 @Override
183 public void actionPerformed(ActionEvent e) {
184 String actionCommand = e.getActionCommand();
185 if (actionCommand.equals("Cut")) {
186 copyToClipBoard(true);
187 } else if (actionCommand.equals("Copy")) {
188 copyToClipBoard(false);
189 } else if (actionCommand.equals("Paste")) {
190 pasteFromClipboard();
191 } else if (actionCommand.equals("Delete")) {
192 deleteSelection();
193 } else if (actionCommand.indexOf(FAST_SELECTION_CMD_PREFIX) == 0) {
194 moveFast(Direction.getDirection(actionCommand
195 .substring(FAST_SELECTION_CMD_PREFIX.length())), true);
196 } else if (actionCommand.indexOf(FAST_PREFIX) == 0) {
197 moveFast(
198 Direction.getDirection(actionCommand.substring(FAST_PREFIX.length())),
199 false);
200 }
201 }
202
203
204
205
206
207
208
209 protected void copyToClipBoard(boolean cut) {
210 StringBuffer buffer = new StringBuffer();
211 int fromX = selModel.getFirstSelectedRow();
212 int fromY = selModel.getFirstSelectedColumn();
213 int toX = selModel.getLastSelectedRow();
214 int toY = selModel.getLastSelectedColumn();
215
216 for (int i = fromX; i <= toX; i++) {
217 for (int j = fromY; j < toY; j++) {
218 buffer.append(grid.getValueAt(i, j));
219 buffer.append('\t');
220 if (cut) {
221 grid.setValueAt("", i, j);
222 }
223 }
224 buffer.append(grid.getValueAt(i, toY));
225 buffer.append('\n');
226 if (cut) {
227 grid.setValueAt("", i, toY);
228 }
229 }
230
231 StringSelection strSelection = new StringSelection(buffer.toString());
232 clipBoard.setContents(strSelection, strSelection);
233
234 if (cut) {
235 grid.repaint();
236 }
237 }
238
239
240
241
242 protected void pasteFromClipboard() {
243
244 String insertString = "";
245
246 try {
247 insertString = (String) (clipBoard.getContents(this)
248 .getTransferData(DataFlavor.stringFlavor));
249 } catch (Exception ex) {
250 SimSystem
251 .report(Level.WARNING, "Could not load data from clipboard.", ex);
252 }
253
254 if (insertString.length() == 0) {
255 return;
256 }
257
258 String rowString;
259 StringTokenizer tokenizer = new StringTokenizer(insertString, "\n");
260
261 int startRow = selModel.getFirstSelectedRow();
262 int startCol = selModel.getFirstSelectedColumn();
263 int rowCount = grid.getRowCount();
264 int colCount = grid.getColumnCount();
265
266 for (int i = 0; tokenizer.hasMoreTokens(); i++) {
267
268 rowString = tokenizer.nextToken();
269 String[] values = rowString.split("\t");
270
271 if (startRow + i >= rowCount) {
272 break;
273 }
274
275 for (int j = 0; j < values.length; j++) {
276 if (startCol + j >= colCount) {
277 continue;
278 }
279 grid.setValueAt(values[j], startRow + i, startCol + j);
280 }
281 }
282
283 grid.repaint();
284 }
285
286
287
288
289 private void deleteSelection() {
290 SelectionModel sModel = grid.getSelectionModel();
291 for (int i = sModel.getFirstSelectedRow(); i <= sModel.getLastSelectedRow(); i++) {
292 for (int j = sModel.getFirstSelectedColumn(); j <= sModel
293 .getLastSelectedColumn(); j++) {
294 grid.setValueAt("", i, j);
295 }
296 }
297 }
298
299
300
301
302
303
304
305
306
307
308
309
310
311 protected void moveFast(Direction direction, boolean select) {
312
313 if (direction == Direction.UNKNOWN) {
314 return;
315 }
316
317 int fromX = selModel.getFirstSelectedRow();
318 int toX = selModel.getLastSelectedRow();
319 int fromY = selModel.getFirstSelectedColumn();
320 int toY = selModel.getLastSelectedColumn();
321
322 int rowCount = grid.getRowCount();
323 int colCount = grid.getColumnCount();
324
325 int currentX = fromX;
326 int currentY = fromY;
327
328 String value = getValue(direction.modifiesRows(), direction.getOffset(),
329 currentX, currentY, rowCount, colCount).toString();
330
331
332 while (!value.equals("")) {
333 if (direction.modifiesRows()) {
334 currentX += direction.getOffset();
335 } else {
336 currentY += direction.getOffset();
337 }
338 value = getValue(direction.modifiesRows(), direction.getOffset(),
339 currentX, currentY, rowCount, colCount).toString();
340 }
341
342 if (select) {
343 selModel.setSelectionRange(Math.min(fromX, currentX),
344 Math.min(fromY, currentY), Math.max(toX, currentX),
345 Math.max(toY, currentY));
346 } else {
347 selModel.setSelectionRange(currentX, currentY, currentX, currentY);
348 }
349
350 grid.repaint();
351 }
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374 protected String getValue(boolean modifyX, int offSet, int currentRow,
375 int currentCol, int rowCount, int colCount) {
376 boolean rowOutOfBounds = (currentRow + offSet < 0 || currentRow + offSet >= rowCount);
377 boolean colOutOfBounds = (currentCol + offSet < 0 || currentCol + offSet >= colCount);
378 if ((modifyX && rowOutOfBounds) || colOutOfBounds) {
379 return "";
380 }
381
382 Object o = modifyX ? grid.getValueAt(currentRow + offSet, currentCol)
383 : grid.getValueAt(currentRow, currentCol + offSet);
384
385 if (o == null) {
386 return "";
387 }
388 return o.toString();
389 }
390 }
391
392
393
394
395
396
397
398
399
400
401
402
403 enum Direction {
404
405
406
407
408 UP,
409
410
411
412
413 DOWN,
414
415
416
417
418 LEFT,
419
420
421
422
423 RIGHT,
424
425
426
427
428
429 UNKNOWN;
430
431
432
433
434
435
436
437
438 static Direction getDirection(String str) {
439 if (str.equals(GridBehaviourAdapter.ACTION_COMMAND_UP)) {
440 return UP;
441 }
442 if (str.equals(GridBehaviourAdapter.ACTION_COMMAND_DOWN)) {
443 return DOWN;
444 }
445 if (str.equals(GridBehaviourAdapter.ACTION_COMMAND_LEFT)) {
446 return LEFT;
447 }
448 if (str.equals(GridBehaviourAdapter.ACTION_COMMAND_RIGHT)) {
449 return RIGHT;
450 }
451 return UNKNOWN;
452 }
453
454
455
456
457
458
459 boolean modifiesRows() {
460 return this == UP || this == DOWN;
461 }
462
463
464
465
466
467
468 boolean modifiesColumns() {
469 return this == LEFT || this == RIGHT;
470 }
471
472
473
474
475
476
477
478
479
480 int getOffset() {
481 return (this == DOWN || this == RIGHT) ? 1 : -1;
482 }
483 }