1 11 12 package org.eclipse.ui.internal.keys; 13 14 import java.util.ArrayList ; 15 import java.util.Collections ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 import java.util.SortedSet ; 19 import java.util.TreeSet ; 20 21 import org.eclipse.swt.SWT; 22 import org.eclipse.swt.events.DisposeEvent; 23 import org.eclipse.swt.events.DisposeListener; 24 import org.eclipse.swt.events.FocusEvent; 25 import org.eclipse.swt.events.FocusListener; 26 import org.eclipse.swt.events.ModifyEvent; 27 import org.eclipse.swt.events.ModifyListener; 28 import org.eclipse.swt.graphics.Font; 29 import org.eclipse.swt.graphics.Point; 30 import org.eclipse.swt.widgets.Display; 31 import org.eclipse.swt.widgets.Event; 32 import org.eclipse.swt.widgets.Listener; 33 import org.eclipse.swt.widgets.Text; 34 import org.eclipse.ui.keys.KeySequence; 35 import org.eclipse.ui.keys.KeyStroke; 36 import org.eclipse.ui.keys.NaturalKey; 37 import org.eclipse.ui.keys.ParseException; 38 import org.eclipse.ui.keys.SWTKeySupport; 39 import org.eclipse.ui.keys.SpecialKey; 40 41 49 public final class KeySequenceText { 50 51 55 private class KeyTrapListener implements Listener { 56 61 private int insertionIndex = -1; 62 63 67 void clearInsertionIndex() { 68 insertionIndex = -1; 69 } 70 71 80 private void deleteKeyStroke(List keyStrokes) { 81 clearInsertionIndex(); 82 83 if (hasSelection()) { 84 88 deleteSelection(keyStrokes, false); 89 90 } else { 91 if (!keyStrokes.isEmpty()) { 93 keyStrokes.remove(keyStrokes.size() - 1); 94 } 95 96 } 97 } 98 99 110 public void handleEvent(Event event) { 111 List keyStrokes = new ArrayList (getKeySequence().getKeyStrokes()); 112 113 if (event.type == SWT.KeyDown) { 115 handleKeyDown(event, keyStrokes); 116 } else if (event.type == SWT.KeyUp) { 117 handleKeyUp(event, keyStrokes); 118 } 119 120 setKeySequence(KeySequence.getInstance(keyStrokes)); 122 123 event.doit = false; 125 } 126 127 139 private void handleKeyDown(Event event, List keyStrokes) { 140 if ((event.character == SWT.BS) && (event.stateMask == 0)) { 142 deleteKeyStroke(keyStrokes); 143 } else { 144 insertKeyStroke(event, keyStrokes); 145 } 146 } 147 148 162 private void handleKeyUp(Event event, List keyStrokes) { 163 if (hasIncompleteStroke()) { 164 168 Event mockEvent = new Event(); 169 if ((event.keyCode & SWT.MODIFIER_MASK) != 0) { 170 mockEvent.stateMask = event.stateMask - event.keyCode; 172 } else { 173 177 mockEvent.stateMask = event.stateMask; 178 } 179 180 184 int key = 185 SWTKeySupport.convertEventToUnmodifiedAccelerator(mockEvent); 186 KeyStroke remainingStroke = 187 SWTKeySupport.convertAcceleratorToKeyStroke(key); 188 if (!keyStrokes.isEmpty()) { 189 keyStrokes.remove(keyStrokes.size() - 1); 190 } 191 if (!remainingStroke.getModifierKeys().isEmpty()) { 192 keyStrokes.add(remainingStroke); 193 } 194 } 195 196 } 197 198 227 private void insertKeyStroke(Event event, List keyStrokes) { 228 int key = SWTKeySupport.convertEventToUnmodifiedAccelerator(event); 230 KeyStroke stroke = SWTKeySupport.convertAcceleratorToKeyStroke(key); 231 232 236 if ((SpecialKey.NUM_LOCK.equals(stroke.getNaturalKey())) 237 || (SpecialKey.CAPS_LOCK.equals(stroke.getNaturalKey())) 238 || (SpecialKey.SCROLL_LOCK.equals(stroke.getNaturalKey()))) { 239 return; 240 } 241 242 if (insertionIndex != -1) { 243 if (stroke.isComplete()) { 245 insertStrokeAt(keyStrokes, stroke, insertionIndex); 246 clearInsertionIndex(); 247 } 248 249 } else if (hasSelection()) { 250 insertionIndex = 252 deleteSelection(keyStrokes, stroke.isComplete()); 253 if ((stroke.isComplete()) 254 || (insertionIndex >= keyStrokes.size())) { 255 insertStrokeAt(keyStrokes, stroke, insertionIndex); 256 clearInsertionIndex(); 257 } 258 259 } else { 260 if ((hasIncompleteStroke()) && (!keyStrokes.isEmpty())) { 262 keyStrokes.remove(keyStrokes.size() - 1); 263 } 264 265 if ((keyStrokes.isEmpty()) 267 || (insertionIndex >= keyStrokes.size()) 268 || (isCursorInLastPosition())) { 269 insertStrokeAt(keyStrokes, stroke, keyStrokes.size()); 270 clearInsertionIndex(); 271 } else { 272 276 insertionIndex = 277 deleteSelection(keyStrokes, stroke.isComplete()); 278 if (stroke.isComplete()) { 279 insertStrokeAt(keyStrokes, stroke, insertionIndex); 280 clearInsertionIndex(); 281 } 282 } 283 284 } 285 } 286 } 287 288 292 private class TraversalFilter implements Listener { 293 302 public void handleEvent(Event event) { 303 switch (event.detail) { 304 case SWT.TRAVERSE_ESCAPE : 305 case SWT.TRAVERSE_MNEMONIC : 306 case SWT.TRAVERSE_NONE : 307 case SWT.TRAVERSE_PAGE_NEXT : 308 case SWT.TRAVERSE_PAGE_PREVIOUS : 309 case SWT.TRAVERSE_RETURN : 310 event.type = SWT.None; 311 event.doit = false; 312 break; 313 314 case SWT.TRAVERSE_TAB_NEXT : 315 case SWT.TRAVERSE_TAB_PREVIOUS : 316 if ((event.stateMask & (SWT.MODIFIER_MASK ^ SWT.SHIFT)) 319 != 0) { 320 event.type = SWT.None; 322 event.doit = false; 323 break; 324 } 325 326 328 case SWT.TRAVERSE_ARROW_NEXT : 329 case SWT.TRAVERSE_ARROW_PREVIOUS : 330 default : 331 if (hasIncompleteStroke()) { 334 List keyStrokes = 335 new ArrayList (getKeySequence().getKeyStrokes()); 336 if (!keyStrokes.isEmpty()) { 337 keyStrokes.remove(keyStrokes.size() - 1); 338 } 339 setKeySequence(KeySequence.getInstance(keyStrokes)); 340 } 341 } 342 343 } 344 } 345 346 350 private class TraversalFilterManager implements FocusListener { 351 352 private TraversalFilter filter = new TraversalFilter(); 353 354 360 public void focusGained(FocusEvent event) { 361 Display.getCurrent().addFilter(SWT.Traverse, filter); 362 } 363 364 370 public void focusLost(FocusEvent event) { 371 Display.getCurrent().removeFilter(SWT.Traverse, filter); 372 } 373 } 374 375 380 private class UpdateSequenceListener implements ModifyListener { 381 387 public void modifyText(ModifyEvent event) { 388 try { 389 KeySequence originalSequence = getKeySequence(); 391 392 String contents = getText(); 394 KeySequence newSequence = KeySequence.getInstance(contents); 395 396 if (!originalSequence.equals(newSequence)) { 398 setKeySequence(newSequence); 399 } 400 401 } catch (ParseException e) { 402 setKeySequence(getKeySequence()); 404 } 405 } 406 } 407 408 static { 409 TreeSet trappedKeys = new TreeSet (); 410 trappedKeys.add(SWTKeySupport.convertAcceleratorToKeyStroke(SWT.TAB)); 411 trappedKeys.add( 412 SWTKeySupport.convertAcceleratorToKeyStroke(SWT.TAB | SWT.SHIFT)); 413 trappedKeys.add(SWTKeySupport.convertAcceleratorToKeyStroke(SWT.BS)); 414 List trappedKeyList = new ArrayList (trappedKeys); 415 TRAPPED_KEYS = Collections.unmodifiableList(trappedKeyList); 416 } 417 418 419 private static final String EMPTY_STRING = ""; 424 public static final int INFINITE = -1; 425 430 public static final List TRAPPED_KEYS; 431 432 435 private final KeyTrapListener keyFilter = new KeyTrapListener(); 436 440 private KeySequence keySequence = KeySequence.getInstance(); 441 442 private int maxStrokes = INFINITE; 443 444 private final Text text; 445 449 private final UpdateSequenceListener updateSequenceListener = 450 new UpdateSequenceListener(); 451 452 460 public KeySequenceText(Text wrappedText) { 461 text = wrappedText; 462 463 if ("carbon".equals(SWT.getPlatform())) { final Font font = new Font(text.getDisplay(), "Lucida Grande", 13, SWT.NORMAL); text.setFont(font); 469 text.addDisposeListener(new DisposeListener() { 470 public void widgetDisposed(DisposeEvent e) { 471 font.dispose(); 472 } 473 }); 474 } 475 476 text.addListener(SWT.KeyUp, keyFilter); 478 text.addListener(SWT.KeyDown, keyFilter); 479 480 text.addFocusListener(new TraversalFilterManager()); 482 483 text.addModifyListener(updateSequenceListener); 485 } 486 487 490 public void clear() { 491 keySequence = KeySequence.getInstance(); 492 text.setText(EMPTY_STRING); 493 } 494 495 512 private int deleteSelection(List keyStrokes, boolean allowIncomplete) { 513 Point selection = text.getSelection(); 515 int start = selection.x; 516 int end = selection.y; 517 518 525 String string = new String (); 526 List currentStrokes = new ArrayList (); 527 Iterator keyStrokeItr = keyStrokes.iterator(); 528 int startTextIndex = 0; while ((string.length() < start) && (keyStrokeItr.hasNext())) { 530 startTextIndex = string.length(); 531 currentStrokes.add(keyStrokeItr.next()); 532 string = KeySequence.getInstance(currentStrokes).format(); 533 } 534 535 539 int startStrokeIndex; 540 if (string.length() == start) { 541 startStrokeIndex = currentStrokes.size(); 542 } else { 543 startStrokeIndex = currentStrokes.size() - 1; 544 } 545 546 551 int endStrokeIndex; 552 if (start == end) { 553 return startStrokeIndex; 554 555 } else { 556 while ((string.length() < end) && (keyStrokeItr.hasNext())) { 557 currentStrokes.add(keyStrokeItr.next()); 558 string = KeySequence.getInstance(currentStrokes).format(); 559 } 560 endStrokeIndex = currentStrokes.size() - 1; 561 if (endStrokeIndex < 0) { 562 endStrokeIndex = 0; 563 } 564 565 } 566 567 571 KeyStroke startStroke = (KeyStroke) keyStrokes.get(startStrokeIndex); 572 while (startStrokeIndex <= endStrokeIndex) { 573 keyStrokes.remove(startStrokeIndex); 574 endStrokeIndex--; 575 } 576 577 581 if (allowIncomplete) { 582 SortedSet modifierKeys = new TreeSet (startStroke.getModifierKeys()); 583 KeyStroke incompleteStroke = 584 KeyStroke.getInstance(modifierKeys, null); 585 int incompleteStrokeLength = incompleteStroke.format().length(); 586 if ((startTextIndex + incompleteStrokeLength) <= start) { 587 keyStrokes.add(startStrokeIndex, incompleteStroke); 588 } 589 } 590 591 return startStrokeIndex; 592 } 593 594 600 public KeySequence getKeySequence() { 601 return keySequence; 602 } 603 604 609 private String getText() { 610 return text.getText(); 611 } 612 613 619 private boolean hasIncompleteStroke() { 620 return !keySequence.isComplete(); 621 } 622 623 629 private boolean hasSelection() { 630 return (text.getSelectionCount() > 0); 631 } 632 633 640 public void insert(KeyStroke stroke) { 641 if (!stroke.isComplete()) { 642 return; 643 } 644 645 List keyStrokes = new ArrayList (getKeySequence().getKeyStrokes()); 647 648 if ((hasIncompleteStroke()) && (!keyStrokes.isEmpty())) { 649 keyStrokes.remove(keyStrokes.size() - 1); 650 } 651 652 int index = deleteSelection(keyStrokes, false); 653 insertStrokeAt(keyStrokes, stroke, index); 654 keyFilter.clearInsertionIndex(); 655 setKeySequence(KeySequence.getInstance(keyStrokes)); 656 } 657 658 674 private void insertStrokeAt(List keyStrokes, KeyStroke stroke, int index) { 675 KeyStroke currentStroke = 676 (index >= keyStrokes.size()) 677 ? null 678 : (KeyStroke) keyStrokes.get(index); 679 if ((currentStroke != null) && (!currentStroke.isComplete())) { 680 SortedSet modifierKeys = 681 new TreeSet (currentStroke.getModifierKeys()); 682 NaturalKey naturalKey = stroke.getNaturalKey(); 683 modifierKeys.addAll(stroke.getModifierKeys()); 684 keyStrokes.remove(index); 685 keyStrokes.add( 686 index, 687 KeyStroke.getInstance(modifierKeys, naturalKey)); 688 } else { 689 keyStrokes.add(index, stroke); 690 } 691 } 692 693 700 private boolean isCursorInLastPosition() { 701 return (text.getSelection().y >= getText().length()); 702 } 703 704 719 public void setKeySequence(KeySequence newKeySequence) { 720 keySequence = newKeySequence; 721 722 if (maxStrokes != INFINITE) { 724 List keyStrokes = new ArrayList (keySequence.getKeyStrokes()); 725 int keyStrokesSize = keyStrokes.size(); 726 for (int i = keyStrokesSize - 1; i >= maxStrokes; i--) { 727 keyStrokes.remove(i); 728 } 729 keySequence = KeySequence.getInstance(keyStrokes); 730 } 731 732 String currentString = getText(); 734 String newString = keySequence.format(); 735 if (!currentString.equals(newString)) { 736 text.removeModifyListener(updateSequenceListener); 738 text.setText(keySequence.format()); 739 text.addModifyListener(updateSequenceListener); 740 text.setSelection(getText().length()); 741 } 742 } 743 744 751 public int getKeyStrokeLimit() { 752 return maxStrokes; 753 } 754 755 763 public void setKeyStrokeLimit(int keyStrokeLimit) { 764 if (keyStrokeLimit > 0 || keyStrokeLimit == INFINITE) 765 this.maxStrokes = keyStrokeLimit; 766 else 767 throw new IllegalArgumentException (); 768 769 setKeySequence(getKeySequence()); 771 } 772 } 773 | Popular Tags |