1 9 package bluej.editor.moe; 10 11 import java.awt.Container ; 12 import java.awt.Event ; 13 import java.awt.Toolkit ; 14 import java.awt.datatransfer.*; 15 import java.awt.event.ActionEvent ; 16 import java.awt.event.KeyAdapter ; 17 import java.awt.event.KeyEvent ; 18 import java.io.*; 19 import java.util.ArrayList ; 20 import java.util.Hashtable ; 21 import java.util.Iterator ; 22 23 import javax.swing.*; 24 import javax.swing.event.DocumentEvent ; 25 import javax.swing.text.*; 26 import javax.swing.undo.CannotRedoException ; 27 import javax.swing.undo.CannotUndoException ; 28 29 import bluej.Config; 30 import bluej.prefmgr.PrefMgr; 31 import bluej.prefmgr.PrefMgrDialog; 32 import bluej.utility.Debug; 33 import bluej.utility.DialogManager; 34 35 46 47 public final class MoeActions 48 { 49 51 private static final String KEYS_FILE = "editor.keys"; 52 53 private static int SHORTCUT_MASK; 54 private static int ALT_SHORTCUT_MASK; 55 private static int SHIFT_SHORTCUT_MASK; 56 private static int SHIFT_ALT_SHORTCUT_MASK; 57 private static int DOUBLE_SHORTCUT_MASK; 59 private static final int tabSize = Config.getPropInteger("bluej.editor.tabsize", 4); 60 private static final String spaces = " "; 61 private static final char TAB_CHAR = '\t'; 62 63 65 private Action[] actionTable; private Hashtable actions; private String [] categories; 68 private int[] categoryIndex; 69 70 private Keymap keymap; private KeyCatcher keyCatcher; 72 73 private boolean lastActionWasCut; public UndoAction undoAction; 76 public RedoAction redoAction; 77 78 public Action compileAction; 80 81 private InputMap componentInputMap; 83 84 86 private static MoeActions moeActions; 87 88 92 public static MoeActions getActions(JTextComponent textComponent) 93 { 94 if (moeActions == null) 95 moeActions = new MoeActions(textComponent); 96 97 if (textComponent != null) 98 textComponent.setKeymap(moeActions.keymap); 99 return moeActions; 100 } 101 102 104 107 private MoeActions(JTextComponent textComponent) 108 { 109 SHORTCUT_MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); 111 112 if (SHORTCUT_MASK == Event.CTRL_MASK) 113 ALT_SHORTCUT_MASK = Event.META_MASK; else 115 ALT_SHORTCUT_MASK = Event.CTRL_MASK; 116 117 SHIFT_SHORTCUT_MASK = SHORTCUT_MASK + Event.SHIFT_MASK; 118 SHIFT_ALT_SHORTCUT_MASK = Event.SHIFT_MASK + ALT_SHORTCUT_MASK; 119 DOUBLE_SHORTCUT_MASK = SHORTCUT_MASK + ALT_SHORTCUT_MASK; 120 121 keymap = JTextComponent.addKeymap("BlueJ map", textComponent.getKeymap()); 123 124 createActionTable(textComponent); 125 keyCatcher = new KeyCatcher(); 126 if (!load()) 127 setDefaultKeyBindings(); 128 lastActionWasCut = false; 129 130 componentInputMap = textComponent.getInputMap(); 132 } 133 134 137 public Action getActionByName(String name) 138 { 139 return (Action) (actions.get(name)); 140 } 141 142 145 public KeyStroke[] getKeyStrokesForAction(Action action) 146 { 147 KeyStroke[] keys = keymap.getKeyStrokesForAction(action); 148 keys = addComponentKeyStrokes(action, keys); if (keys != null && keys.length > 0) 150 return keys; 151 else 152 return null; 153 } 154 155 160 public KeyStroke[] addComponentKeyStrokes(Action action, KeyStroke[] keys) 161 { 162 ArrayList keyStrokes = null; 163 KeyStroke[] componentKeys = componentInputMap.allKeys(); 164 165 for (int i = 0; i < componentKeys.length; i++) { 167 if (componentInputMap.get(componentKeys[i]).equals(action.getValue(Action.NAME))) { 168 if (keyStrokes == null) 169 keyStrokes = new ArrayList (); 170 keyStrokes.add(componentKeys[i]); 171 } 172 } 173 174 if (keyStrokes != null) { 176 for (Iterator i = keyStrokes.iterator(); i.hasNext();) { 177 if (keymap.getAction((KeyStroke) i.next()) != null) { 178 i.remove(); 179 } 180 } 181 } 182 183 if ((keyStrokes == null) || (keyStrokes.size() == 0)) 185 return keys; 186 187 KeyStroke[] allKeys; 188 if (keys == null) { 189 allKeys = new KeyStroke[keyStrokes.size()]; 190 keyStrokes.toArray(allKeys); 191 } 192 else { allKeys = new KeyStroke[keyStrokes.size() + keys.length]; 194 keyStrokes.toArray(allKeys); 195 System.arraycopy(allKeys, 0, allKeys, keys.length, keyStrokes.size()); 196 System.arraycopy(keys, 0, allKeys, 0, keys.length); 197 } 198 return allKeys; 199 } 200 201 204 public void addActionForKeyStroke(KeyStroke key, Action a) 205 { 206 keymap.addActionForKeyStroke(key, a); 207 } 208 209 212 public void removeKeyStrokeBinding(KeyStroke key) 213 { 214 keymap.removeKeyStrokeBinding(key); 215 } 216 217 220 public boolean save() 221 { 222 try { 223 File file = Config.getUserConfigFile(KEYS_FILE); 224 FileOutputStream ostream = new FileOutputStream(file); 225 ObjectOutputStream stream = new ObjectOutputStream(ostream); 226 KeyStroke[] keys = keymap.getBoundKeyStrokes(); 227 stream.writeInt(MoeEditor.version); 228 stream.writeInt(keys.length); 229 for (int i = 0; i < keys.length; i++) { 230 stream.writeObject(keys[i]); 231 stream.writeObject(keymap.getAction(keys[i]).getValue(Action.NAME)); 232 } 233 stream.flush(); 234 ostream.close(); 235 return true; 236 } 237 catch (Exception exc) { 238 Debug.message("Cannot save key bindings: " + exc); 239 return false; 240 } 241 } 242 243 246 public boolean load() 247 { 248 try { 249 File file = Config.getUserConfigFile(KEYS_FILE); 250 FileInputStream istream = new FileInputStream(file); 251 ObjectInputStream stream = new ObjectInputStream(istream); 252 int version = 0; 254 int count = stream.readInt(); 255 if (count > 100) { version = count; 257 count = stream.readInt(); 258 } 259 if (Config.isMacOS() && (version < 140)) { 260 return false; 263 } 264 265 for (int i = 0; i < count; i++) { 266 KeyStroke key = (KeyStroke) stream.readObject(); 267 String actionName = (String ) stream.readObject(); 268 Action action = (Action) (actions.get(actionName)); 269 if (action != null) { 270 keymap.addActionForKeyStroke(key, action); 271 } 272 } 273 istream.close(); 274 275 277 if (version < 130) { 278 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), 279 (Action) (actions.get("indent"))); 280 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, Event.SHIFT_MASK), 281 (Action) (actions.get("insert-tab"))); 282 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), 283 (Action) (actions.get("new-line"))); 284 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, Event.SHIFT_MASK), 285 (Action) (actions.get("insert-break"))); 286 } 287 if (version < 200) { 288 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, Event.SHIFT_MASK), 289 (Action) (actions.get("de-indent"))); 290 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_I, SHORTCUT_MASK), 291 (Action) (actions.get("insert-tab"))); 292 } 293 return true; 294 } 295 catch (Exception exc) { 296 return false; 298 } 299 } 300 301 305 public void userAction() 306 { 307 lastActionWasCut = false; 308 } 309 310 313 public void textInsertAction(DocumentEvent evt, JTextComponent textPane) 314 { 315 try { 316 if (evt.getLength() == 1) { Document doc = evt.getDocument(); 318 int offset = evt.getOffset(); 319 char ch = doc.getText(offset, 1).charAt(0); 320 321 325 if (ch == '}') { 326 closingBrace(textPane, doc, offset); 327 } 328 } 329 } 330 catch (BadLocationException e) {} 331 } 332 333 336 private void closingBrace(JTextComponent textPane, Document doc, int offset) 337 throws BadLocationException 338 { 339 int lineIndex = getCurrentLineIndex(textPane); 340 Element line = getLine(textPane, lineIndex); 341 int lineStart = line.getStartOffset(); 342 String prefix = doc.getText(lineStart, offset - lineStart); 343 344 if(prefix.trim().length() == 0) { textPane.setCaretPosition(lineStart); 346 doIndent(textPane, true); 347 textPane.setCaretPosition(textPane.getCaretPosition() + 1); 348 } 349 } 350 351 355 366 abstract class MoeAbstractAction extends TextAction 367 { 368 369 public MoeAbstractAction(String name) 370 { 371 super(name); 372 } 373 374 375 protected final MoeEditor getEditor(ActionEvent e) 376 { 377 MoeEditor ed = null; 378 379 Object source = e.getSource(); 381 if (source instanceof JComponent) { 382 Container c = ((JComponent) source).getTopLevelAncestor(); 383 if (c instanceof MoeEditor) 384 ed = (MoeEditor) c; 385 } 386 387 if (ed == null) { 389 JTextComponent textComponent = getTextComponent(e); 390 if (textComponent != null) { 391 Container c = textComponent.getTopLevelAncestor(); 392 if (c instanceof MoeEditor) 393 ed = (MoeEditor) c; 394 } 395 } 396 397 if (ed != null) 398 ed.clearMessage(); 399 return ed; 400 } 401 } 402 403 406 class SaveAction extends MoeAbstractAction 407 { 408 409 public SaveAction() 410 { 411 super("save"); 412 } 413 414 public void actionPerformed(ActionEvent e) 415 { 416 getEditor(e).userSave(); 417 } 418 } 419 420 422 426 class ReloadAction extends MoeAbstractAction 427 { 428 429 public ReloadAction() 430 { 431 super("reload"); 432 } 433 434 public void actionPerformed(ActionEvent e) 435 { 436 getEditor(e).reload(); 437 } 438 } 439 440 442 class PrintAction extends MoeAbstractAction 443 { 444 445 public PrintAction() 446 { 447 super("print"); 448 } 449 450 public void actionPerformed(ActionEvent e) 451 { 452 getEditor(e).print(); 453 } 454 } 455 456 458 class PageSetupAction extends MoeAbstractAction 459 { 460 461 public PageSetupAction() 462 { 463 super("page-setup"); 464 } 465 466 public void actionPerformed(ActionEvent e) 467 { 468 getEditor(e).pageSetup(); 469 } 470 } 471 472 474 class CloseAction extends MoeAbstractAction 475 { 476 477 public CloseAction() 478 { 479 super("close"); 480 } 481 482 public void actionPerformed(ActionEvent e) 483 { 484 getEditor(e).close(); 485 } 486 } 487 488 491 class UndoAction extends MoeAbstractAction 492 { 493 494 public UndoAction() 495 { 496 super("undo"); 497 this.setEnabled(false); 498 } 499 500 public void actionPerformed(ActionEvent e) 501 { 502 MoeEditor editor = getEditor(e); 503 try { 504 editor.undoManager.undo(); 505 } 506 catch (CannotUndoException ex) { 507 Debug.message("moe: cannot undo..."); 508 } 509 editor.updateUndoControls(); 510 editor.updateRedoControls(); 511 } 512 } 513 514 516 class RedoAction extends MoeAbstractAction 517 { 518 519 public RedoAction() 520 { 521 super("redo"); 522 this.setEnabled(false); 523 } 524 525 public void actionPerformed(ActionEvent e) 526 { 527 MoeEditor editor = getEditor(e); 528 try { 529 editor.undoManager.redo(); 530 } 531 catch (CannotRedoException ex) { 532 Debug.message("moe: cannot redo..."); 533 } 534 editor.updateUndoControls(); 535 editor.updateRedoControls(); 536 } 537 } 538 539 541 class CommentBlockAction extends MoeAbstractAction 542 { 543 544 public CommentBlockAction() 545 { 546 super("comment-block"); 547 } 548 549 public void actionPerformed(ActionEvent e) 550 { 551 getEditor(e); 552 blockAction(getTextComponent(e), new CommentLineAction()); 553 } 554 } 555 556 558 class UncommentBlockAction extends MoeAbstractAction 559 { 560 561 public UncommentBlockAction() 562 { 563 super("uncomment-block"); 564 } 565 566 public void actionPerformed(ActionEvent e) 567 { 568 getEditor(e); 569 blockAction(getTextComponent(e), new UncommentLineAction()); 570 } 571 } 572 573 575 class IndentBlockAction extends MoeAbstractAction 576 { 577 578 public IndentBlockAction() 579 { 580 super("indent-block"); 581 } 582 583 public void actionPerformed(ActionEvent e) 584 { 585 getEditor(e); 586 blockAction(getTextComponent(e), new IndentLineAction()); 587 } 588 } 589 590 592 class DeindentBlockAction extends MoeAbstractAction 593 { 594 595 public DeindentBlockAction() 596 { 597 super("deindent-block"); 598 } 599 600 public void actionPerformed(ActionEvent e) 601 { 602 getEditor(e); 603 blockAction(getTextComponent(e), new DeindentLineAction()); 604 } 605 } 606 607 609 class InsertMethodAction extends MoeAbstractAction 610 { 611 612 public InsertMethodAction() 613 { 614 super("insert-method"); 615 } 616 617 public void actionPerformed(ActionEvent e) 618 { 619 getEditor(e); 620 insertTemplate(getTextComponent(e), "method"); 621 } 622 } 623 624 626 class IndentAction extends MoeAbstractAction 627 { 628 629 public IndentAction() 630 { 631 super("indent"); 632 } 633 634 public void actionPerformed(ActionEvent e) 635 { 636 JTextComponent textPane = getTextComponent(e); 637 MoeEditor ed = getEditor(e); 638 639 int converted = 0; 641 if (ed.checkExpandTabs()) converted = convertTabsToSpaces(textPane); 643 644 if (PrefMgr.getFlag(PrefMgr.AUTO_INDENT)) 645 doIndent(textPane, false); 646 else 647 insertSpacedTab(textPane); 648 649 if (converted > 0) 650 ed.writeMessage(Config.getString("editor.info.tabsExpanded")); 651 } 652 } 653 654 656 class DeIndentAction extends MoeAbstractAction 657 { 658 659 public DeIndentAction() 660 { 661 super("de-indent"); 662 } 663 664 public void actionPerformed(ActionEvent e) 665 { 666 JTextComponent textPane = getTextComponent(e); 667 MoeEditor ed = getEditor(e); 668 669 if (ed.checkExpandTabs()) { int converted = convertTabsToSpaces(textPane); 672 673 if (converted > 0) 674 ed.writeMessage(Config.getString("editor.info.tabsExpanded")); 675 } 676 doDeIndent(textPane); 677 } 678 } 679 680 682 class NewLineAction extends MoeAbstractAction 683 { 684 685 public NewLineAction() 686 { 687 super("new-line"); 688 } 689 690 public void actionPerformed(ActionEvent e) 691 { 692 693 Action action = (Action) (actions.get(DefaultEditorKit.insertBreakAction)); 694 action.actionPerformed(e); 695 696 if (PrefMgr.getFlag(PrefMgr.AUTO_INDENT)) { 697 JTextComponent textPane = getTextComponent(e); 698 doIndent(textPane, true); 699 } 700 } 701 } 702 703 705 class CopyLineAction extends MoeAbstractAction 706 { 707 708 public CopyLineAction() 709 { 710 super("copy-line"); 711 } 712 713 public void actionPerformed(ActionEvent e) 714 { 715 boolean addToClipboard = lastActionWasCut; 716 getActionByName("caret-begin-line").actionPerformed(e); 717 getActionByName("selection-down").actionPerformed(e); 718 if (addToClipboard) 719 addSelectionToClipboard(getTextComponent(e)); 720 else 721 getActionByName("copy-to-clipboard").actionPerformed(e); 722 lastActionWasCut = true; 723 } 724 } 725 726 728 class CutLineAction extends MoeAbstractAction 729 { 730 731 public CutLineAction() 732 { 733 super("cut-line"); 734 } 735 736 public void actionPerformed(ActionEvent e) 737 { 738 boolean addToClipboard = lastActionWasCut; 739 getActionByName("caret-begin-line").actionPerformed(e); 740 getActionByName("selection-down").actionPerformed(e); 741 if (addToClipboard) { 742 addSelectionToClipboard(getTextComponent(e)); 743 getActionByName("delete-previous").actionPerformed(e); 744 } 745 else 746 getActionByName("cut-to-clipboard").actionPerformed(e); 747 lastActionWasCut = true; 748 } 749 } 750 751 753 class CutEndOfLineAction extends MoeAbstractAction 754 { 755 756 public CutEndOfLineAction() 757 { 758 super("cut-end-of-line"); 759 } 760 761 public void actionPerformed(ActionEvent e) 762 { 763 boolean addToClipboard = lastActionWasCut; 764 765 getActionByName("selection-end-line").actionPerformed(e); 766 JTextComponent textComponent = getTextComponent(e); 767 String selection = textComponent.getSelectedText(); 768 if (selection == null) 769 getActionByName("selection-forward").actionPerformed(e); 770 771 if (addToClipboard) { 772 addSelectionToClipboard(textComponent); 773 getActionByName("delete-previous").actionPerformed(e); 774 } 775 else 776 getActionByName("cut-to-clipboard").actionPerformed(e); 777 lastActionWasCut = true; 778 } 779 } 780 781 783 class CutWordAction extends MoeAbstractAction 784 { 785 786 public CutWordAction() 787 { 788 super("cut-word"); 789 } 790 791 public void actionPerformed(ActionEvent e) 792 { 793 boolean addToClipboard = lastActionWasCut; 794 getActionByName("caret-previous-word").actionPerformed(e); 795 getActionByName("selection-next-word").actionPerformed(e); 796 if (addToClipboard) { 797 addSelectionToClipboard(getTextComponent(e)); 798 getActionByName("delete-previous").actionPerformed(e); 799 } 800 else 801 getActionByName("cut-to-clipboard").actionPerformed(e); 802 lastActionWasCut = true; 803 } 804 } 805 806 808 class CutEndOfWordAction extends MoeAbstractAction 809 { 810 811 public CutEndOfWordAction() 812 { 813 super("cut-end-of-word"); 814 } 815 816 public void actionPerformed(ActionEvent e) 817 { 818 boolean addToClipboard = lastActionWasCut; 819 getActionByName("selection-next-word").actionPerformed(e); 820 if (addToClipboard) { 821 addSelectionToClipboard(getTextComponent(e)); 822 getActionByName("delete-previous").actionPerformed(e); 823 } 824 else 825 getActionByName("cut-to-clipboard").actionPerformed(e); 826 lastActionWasCut = true; 827 } 828 } 829 830 832 834 class FindAction extends MoeAbstractAction 835 { 836 837 public FindAction() 838 { 839 super("find"); 840 } 841 842 public void actionPerformed(ActionEvent e) 843 { 844 getEditor(e).find(); 845 } 846 } 847 848 850 class FindNextAction extends MoeAbstractAction 851 { 852 853 public FindNextAction() 854 { 855 super("find-next"); 856 } 857 858 public void actionPerformed(ActionEvent e) 859 { 860 getEditor(e).findNext(); 861 } 862 } 863 864 866 class FindNextBackwardAction extends MoeAbstractAction 867 { 868 869 public FindNextBackwardAction() 870 { 871 super("find-next-backward"); 872 } 873 874 public void actionPerformed(ActionEvent e) 875 { 876 getEditor(e).findNextBackward(); 877 } 878 } 879 880 882 class ReplaceAction extends MoeAbstractAction 883 { 884 885 public ReplaceAction() 886 { 887 super("replace"); 888 } 889 890 public void actionPerformed(ActionEvent e) 891 { 892 getEditor(e).replace(); 893 } 894 } 895 896 898 class CompileAction extends MoeAbstractAction 899 { 900 901 public CompileAction() 902 { 903 super("compile"); 904 } 905 906 public void actionPerformed(ActionEvent e) 907 { 908 getEditor(e).compile(); 909 } 910 } 911 912 914 class ToggleInterfaceAction extends MoeAbstractAction 915 { 916 917 public ToggleInterfaceAction() 918 { 919 super("toggle-interface-view"); 920 } 921 922 public void actionPerformed(ActionEvent e) 923 { 924 Object source = e.getSource(); 925 if (source instanceof JComboBox) 926 getEditor(e).toggleInterface(); 927 else 928 getEditor(e).toggleInterfaceMenu(); 929 } 930 } 931 932 935 class ToggleBreakPointAction extends MoeAbstractAction 936 { 937 938 public ToggleBreakPointAction() 939 { 940 super("toggle-breakpoint"); 941 } 942 943 public void actionPerformed(ActionEvent e) 944 { 945 getEditor(e).toggleBreakpoint(); 946 } 947 } 948 949 952 class KeyBindingsAction extends MoeAbstractAction 953 { 954 955 public KeyBindingsAction() 956 { 957 super("key-bindings"); 958 } 959 960 public void actionPerformed(ActionEvent e) 961 { 962 FunctionDialog dlg = new FunctionDialog(getEditor(e), actionTable, categories, categoryIndex); 963 964 dlg.setVisible(true); 965 } 966 } 967 968 970 class PreferencesAction extends MoeAbstractAction 971 { 972 973 public PreferencesAction() 974 { 975 super("preferences"); 976 } 977 978 public void actionPerformed(ActionEvent e) 979 { 980 PrefMgrDialog.showDialog(0); } 983 } 984 985 988 class AboutAction extends MoeAbstractAction 989 { 990 991 public AboutAction() 992 { 993 super("about-editor"); 994 } 995 996 public void actionPerformed(ActionEvent e) 997 { 998 JOptionPane.showMessageDialog(getEditor(e), new String []{"Moe", "Version " + MoeEditor.versionString, " ", 999 "Moe is the editor of the BlueJ programming environment.", 1000 "Written by Michael K\u00F6lling (mik@bluej.org)."}, "About Moe", JOptionPane.INFORMATION_MESSAGE); 1001 } 1002 } 1003 1004 1006 class DescribeKeyAction extends MoeAbstractAction 1007 { 1008 1009 public DescribeKeyAction() 1010 { 1011 super("describe-key"); 1012 } 1013 1014 public void actionPerformed(ActionEvent e) 1015 { 1016 JTextComponent textComponent = getTextComponent(e); 1017 textComponent.addKeyListener(keyCatcher); 1018 MoeEditor ed = getEditor(e); 1019 keyCatcher.setEditor(ed); 1020 ed.writeMessage("Describe key: "); 1021 } 1022 } 1023 1024 1026 class HelpMouseAction extends MoeAbstractAction 1027 { 1028 1029 public HelpMouseAction() 1030 { 1031 super("help-mouse"); 1032 } 1033 1034 public void actionPerformed(ActionEvent e) 1035 { 1036 JOptionPane.showMessageDialog(getEditor(e), new String []{"Moe Mouse Buttons:", " ", "left button:", 1037 " click: place cursor", " double-click: select word", " triple-click: select line", 1038 " drag: make selection", " ", "right button:", " (currently unused)",}, "Moe Mouse Buttons", 1039 JOptionPane.INFORMATION_MESSAGE); 1040 } 1041 } 1042 1043 1045 class ShowManualAction extends MoeAbstractAction 1046 { 1047 1048 public ShowManualAction() 1049 { 1050 super("show-manual"); 1051 } 1052 1053 public void actionPerformed(ActionEvent e) 1054 { 1055 DialogManager.NYI(getEditor(e)); 1056 } 1057 } 1058 1059 1061 class GoToLineAction extends MoeAbstractAction 1062 { 1063 1064 public GoToLineAction() 1065 { 1066 super("go-to-line"); 1067 } 1068 1069 public void actionPerformed(ActionEvent e) 1070 { 1071 getEditor(e).goToLine(); 1072 } 1073 } 1074 1075 1087 1089 1092 public void addSelectionToClipboard(JTextComponent textComponent) 1093 { 1094 Clipboard clipboard = textComponent.getToolkit().getSystemClipboard(); 1095 1096 Transferable content = clipboard.getContents(this); 1098 String clipContent = ""; 1099 if (content != null) { 1100 try { 1101 clipContent = (String ) (content.getTransferData(DataFlavor.stringFlavor)); 1102 } 1103 catch (Exception exc) {} } 1105 1106 StringSelection contents = new StringSelection(clipContent + textComponent.getSelectedText()); 1108 clipboard.setContents(contents, contents); 1109 } 1110 1111 1115 1124 private int getCurrentColumn(JTextComponent textPane) 1125 { 1126 Caret caret = textPane.getCaret(); 1127 int pos = Math.min(caret.getMark(), caret.getDot()); 1128 AbstractDocument doc = (AbstractDocument) textPane.getDocument(); 1129 int lineStart = doc.getParagraphElement(pos).getStartOffset(); 1130 return (pos - lineStart); 1131 } 1132 1133 1137 private Element getLine(JTextComponent text, int lineNo) 1138 { 1139 return text.getDocument().getDefaultRootElement().getElement(lineNo); 1140 } 1141 1142 1146 private Element getLineAt(JTextComponent text, int pos) 1147 { 1148 MoeSyntaxDocument document = (MoeSyntaxDocument) text.getDocument(); 1149 return document.getParagraphElement(pos); 1150 } 1151 1152 1156 private int getCurrentLineIndex(JTextComponent text) 1157 { 1158 MoeSyntaxDocument document = (MoeSyntaxDocument) text.getDocument(); 1159 return document.getDefaultRootElement().getElementIndex(text.getCaretPosition()); 1160 } 1161 1162 1164 1169 private void doIndent(JTextComponent textPane, boolean isNewLine) 1170 { 1171 int lineIndex = getCurrentLineIndex(textPane); 1172 if (lineIndex == 0) { if(!isNewLine) 1174 insertSpacedTab(textPane); 1175 return; 1176 } 1177 1178 MoeSyntaxDocument doc = (MoeSyntaxDocument) textPane.getDocument(); 1179 1180 Element line = getLine(textPane, lineIndex); 1181 int lineStart = line.getStartOffset(); 1182 int pos = textPane.getCaretPosition(); 1183 1184 try { 1185 boolean isOpenBrace = false; 1186 boolean isCommentEnd = false, isCommentEndOnly = false; 1187 1188 1190 String prefix = doc.getText(lineStart, pos - lineStart); 1191 if (prefix.trim().length() > 0) { 1192 insertSpacedTab(textPane); 1193 return; 1194 } 1195 1196 1198 boolean foundLine = false; 1199 int lineOffset = 1; 1200 String prevLineText = null; 1201 while ((lineIndex - lineOffset >= 0) && !foundLine) { 1202 Element prevline = getLine(textPane, lineIndex - lineOffset); 1203 int prevLineStart = prevline.getStartOffset(); 1204 int prevLineEnd = prevline.getEndOffset(); 1205 prevLineText = doc.getText(prevLineStart, prevLineEnd - prevLineStart); 1206 if(!isWhiteSpaceOnly(prevLineText)) { 1207 foundLine = true; 1208 } 1209 else { 1210 lineOffset++; 1211 } 1212 } 1213 if(!foundLine) { 1214 if(!isNewLine) 1215 insertSpacedTab(textPane); 1216 return; 1217 } 1218 1219 if (isOpenBrace(prevLineText)) 1220 isOpenBrace = true; 1221 else { 1222 isCommentEnd = prevLineText.trim().endsWith("*/"); 1223 isCommentEndOnly = prevLineText.trim().equals("*/"); 1224 } 1225 1226 int indentPos = findFirstNonIndentChar(prevLineText, isCommentEnd); 1227 1228 1231 int caretColumn = getCurrentColumn(textPane); 1232 if (caretColumn >= indentPos) { 1233 if (!isNewLine) 1234 insertSpacedTab(textPane); 1235 return; 1236 } 1237 1238 String indent = prevLineText.substring(0, indentPos); 1239 1240 if (isNewLine && isCommentStart(indent)) { 1241 completeNewCommentBlock(textPane, indent); 1242 return; 1243 } 1244 1245 1247 int lineEnd = line.getEndOffset(); 1248 String lineText = doc.getText(lineStart, lineEnd - lineStart); 1249 indentPos = findFirstNonIndentChar(lineText, true); 1250 char firstChar = lineText.charAt(indentPos); 1251 doc.remove(lineStart, indentPos); 1252 doc.insertString(lineStart, nextIndent(indent, isOpenBrace, isCommentEndOnly), null); 1253 if(firstChar == '}') 1254 removeTab(textPane, doc); 1255 } 1256 catch (BadLocationException exc) {} 1257 } 1258 1259 1262 private boolean isWhiteSpaceOnly(String s) 1263 { 1264 return s.trim().length() == 0; 1265 } 1266 1267 1272 private void doDeIndent(JTextComponent textPane) 1273 { 1274 1278 int lineIndex = getCurrentLineIndex(textPane); 1279 MoeSyntaxDocument doc = (MoeSyntaxDocument) textPane.getDocument(); 1280 1281 try { 1282 Element line = getLine(textPane, lineIndex); 1283 int lineStart = line.getStartOffset(); 1284 int lineEnd = line.getEndOffset(); 1285 String lineText = doc.getText(lineStart, lineEnd - lineStart); 1286 1287 int currentIndentPos = findFirstNonIndentChar(lineText, true); 1288 char firstChar = lineText.charAt(currentIndentPos); 1289 1290 textPane.setCaretPosition(lineStart + currentIndentPos); 1291 1292 if (lineIndex == 0) { removeTab(textPane, doc); 1294 return; 1295 } 1296 1297 1299 Element prevline = getLine(textPane, lineIndex - 1); 1300 int prevLineStart = prevline.getStartOffset(); 1301 int prevLineEnd = prevline.getEndOffset(); 1302 String prevLineText = doc.getText(prevLineStart, prevLineEnd - prevLineStart); 1303 1304 int targetIndentPos = findFirstNonIndentChar(prevLineText, true); 1305 1306 if (currentIndentPos > targetIndentPos) { 1307 String indent = prevLineText.substring(0, targetIndentPos); 1309 doc.remove(lineStart, currentIndentPos); 1310 doc.insertString(lineStart, indent, null); 1311 if(firstChar == '}') 1312 removeTab(textPane, doc); 1313 } 1314 else { 1315 removeTab(textPane, doc); 1318 } 1319 } 1320 catch (BadLocationException exc) {} 1321 } 1322 1323 1326 private boolean isCommentStart(String s) 1327 { 1328 s = s.trim(); 1329 return s.endsWith("/**") || s.endsWith("/*"); 1330 } 1331 1332 1338 private void completeNewCommentBlock(JTextComponent textPane, String indentString) 1339 { 1340 String nextIndent = indentString.substring(0, indentString.length() - 2); 1341 textPane.replaceSelection(nextIndent + " * "); 1342 int pos = textPane.getCaretPosition(); 1343 textPane.replaceSelection("\n"); 1344 textPane.replaceSelection(nextIndent + " */"); 1345 textPane.setCaretPosition(pos); 1346 } 1347 1348 1351 private boolean isOpenBrace(String s) 1352 { 1353 int index = s.lastIndexOf('{'); 1354 if (index == -1) 1355 return false; 1356 1357 return s.indexOf('}', index + 1) == -1; 1358 } 1359 1360 1364 private int findFirstNonIndentChar(String s, boolean whitespaceOnly) 1365 { 1366 int cnt = 0; 1367 char ch = s.charAt(0); 1368 1369 1372 if (whitespaceOnly) { 1373 while (ch == ' ' || ch == '\t') { cnt++; 1375 ch = s.charAt(cnt); 1376 } 1377 } 1378 else { 1379 while (ch == ' ' || ch == '\t' || ch == '*') { cnt++; 1381 ch = s.charAt(cnt); 1382 } 1383 if ((s.charAt(cnt) == '/') && (s.charAt(cnt + 1) == '*')) 1384 cnt += 2; 1385 } 1386 return cnt; 1387 } 1388 1389 1393 private String nextIndent(String s, boolean openBrace, boolean commentEndOnly) 1394 { 1395 if (openBrace) 1397 return s + spaces.substring(0, tabSize); 1398 1399 if (commentEndOnly) 1400 return s.substring(0, s.length() - 1); 1401 1402 if (s.endsWith("/*")) 1403 return s.substring(0, s.length() - 2) + " * "; 1404 1405 return s; 1406 } 1407 1408 1411 private void insertSpacedTab(JTextComponent textPane) 1412 { 1413 int numSpaces = tabSize - (getCurrentColumn(textPane) % tabSize); 1414 textPane.replaceSelection(spaces.substring(0, numSpaces)); 1415 } 1416 1417 1423 private void removeTab(JTextComponent textPane, Document doc) 1424 throws BadLocationException 1425 { 1426 int col = getCurrentColumn(textPane); 1427 if(col > 0) { 1428 int remove = col % tabSize; 1429 if(remove == 0) 1430 remove = tabSize; 1431 int pos = textPane.getCaretPosition(); 1432 doc.remove(pos-remove, remove); 1433 } 1434 } 1435 1436 1443 private int convertTabsToSpaces(JTextComponent textPane) 1444 { 1445 int count = 0; 1446 int lineNo = 0; 1447 AbstractDocument doc = (AbstractDocument) textPane.getDocument(); 1448 Element root = doc.getDefaultRootElement(); 1449 Element line = root.getElement(lineNo); 1450 try { 1451 while (line != null) { 1452 int start = line.getStartOffset(); 1453 int length = line.getEndOffset() - start; 1454 String text = doc.getText(start, length); 1455 int startCount = count; 1456 int tabIndex = text.indexOf('\t'); 1457 while (tabIndex != -1) { 1458 text = expandTab(text, tabIndex); 1459 count++; 1460 tabIndex = text.indexOf('\t'); 1461 } 1462 if (count != startCount) { doc.remove(start, length); 1464 doc.insertString(start, text, null); 1465 } 1466 lineNo++; 1467 line = root.getElement(lineNo); 1468 } 1469 } 1470 catch (BadLocationException exc) { 1471 Debug.reportError("stuffed up in 'convertTabsToSpaces'"); 1472 } 1473 return count; 1474 } 1475 1476 private String expandTab(String s, int idx) 1477 { 1478 int numSpaces = tabSize - (idx % tabSize); 1479 return s.substring(0, idx) + spaces.substring(0, numSpaces) + s.substring(idx + 1); 1480 } 1481 1482 1494 private void insertTemplate(JTextComponent textPane, String templateName) 1495 { 1496 try { 1497 File template = Config.getTemplateFile(templateName); 1498 BufferedReader in = new BufferedReader(new FileReader(template)); 1499 int pos = textPane.getCaretPosition(); 1500 int column = getCurrentColumn(textPane); 1501 if (column > 40) 1502 column = 40; 1503 String line = in.readLine(); 1504 while (line != null) { 1505 while ((line.length() > 0) && (line.charAt(0) == '\t')) { 1506 insertSpacedTab(textPane); 1507 line = line.substring(1); 1508 } 1509 textPane.replaceSelection(line); 1510 textPane.replaceSelection("\n"); 1511 textPane.replaceSelection(spaces.substring(0, column)); line = in.readLine(); 1513 } 1514 textPane.setCaretPosition(pos); 1515 } 1516 catch (IOException exc) { 1517 Debug.reportError("Could not read method template."); 1518 Debug.reportError("Exception: " + exc); 1519 } 1520 } 1521 1522 1525 private void blockAction(JTextComponent textPane, LineAction lineAction) 1526 { 1527 Caret caret = textPane.getCaret(); 1528 int selectionStart = caret.getMark(); 1529 int selectionEnd = caret.getDot(); 1530 if (selectionStart > selectionEnd) { 1531 int tmp = selectionStart; 1532 selectionStart = selectionEnd; 1533 selectionEnd = tmp; 1534 } 1535 if (selectionStart != selectionEnd) 1536 selectionEnd = selectionEnd - 1; 1538 MoeSyntaxDocument doc = (MoeSyntaxDocument) textPane.getDocument(); 1539 Element text = doc.getDefaultRootElement(); 1540 1541 int firstLineIndex = text.getElementIndex(selectionStart); 1542 int lastLineIndex = text.getElementIndex(selectionEnd); 1543 for (int i = firstLineIndex; i <= lastLineIndex; i++) { 1544 Element line = text.getElement(i); 1545 lineAction.apply(line, doc); 1546 } 1547 1548 textPane.setCaretPosition(text.getElement(firstLineIndex).getStartOffset()); 1549 textPane.moveCaretPosition(text.getElement(lastLineIndex).getEndOffset()); 1550 } 1551 1552 1554 1557 private void createActionTable(JTextComponent textComponent) 1558 { 1559 undoAction = new UndoAction(); 1560 redoAction = new RedoAction(); 1561 compileAction = new CompileAction(); 1562 1563 1565 Action[] textActions = textComponent.getActions(); 1566 Action[] myActions = { 1567 new SaveAction(), 1568 new ReloadAction(), 1569 new PageSetupAction(), 1570 new PrintAction(), 1571 new CloseAction(), 1572 1573 undoAction, 1574 redoAction, 1575 new CommentBlockAction(), 1576 new UncommentBlockAction(), 1577 new IndentBlockAction(), 1578 new DeindentBlockAction(), 1579 new InsertMethodAction(), 1580 new IndentAction(), 1581 new DeIndentAction(), 1582 new NewLineAction(), 1583 new CopyLineAction(), 1584 new CutLineAction(), 1585 new CutEndOfLineAction(), 1586 new CutWordAction(), 1587 new CutEndOfWordAction(), 1588 1589 new FindAction(), 1590 new FindNextAction(), 1591 new FindNextBackwardAction(), 1592 new ReplaceAction(), 1593 compileAction, 1594 new GoToLineAction(), 1595 new ToggleInterfaceAction(), 1596 new ToggleBreakPointAction(), 1597 1598 new KeyBindingsAction(), 1599 new PreferencesAction(), 1600 1601 new AboutAction(), 1602 new DescribeKeyAction(), 1603 new HelpMouseAction(), 1604 new ShowManualAction(), 1605 }; 1606 1607 1609 actions = new Hashtable (); 1610 1611 Action action; 1612 for (int i = 0; i < textActions.length; i++) { 1613 action = textActions[i]; 1614 actions.put(action.getValue(Action.NAME), action); 1616 } 1617 for (int i = 0; i < myActions.length; i++) { 1618 action = myActions[i]; 1619 actions.put(action.getValue(Action.NAME), action); 1620 } 1621 1622 1624 actionTable = new Action[] { 1625 1626 1628 (Action) (actions.get(DefaultEditorKit.deletePrevCharAction)), (Action) (actions.get(DefaultEditorKit.deleteNextCharAction)), 1630 (Action) (actions.get(DefaultEditorKit.copyAction)), 1631 (Action) (actions.get(DefaultEditorKit.cutAction)), 1632 (Action) (actions.get("copy-line")), 1633 (Action) (actions.get("cut-line")), 1634 (Action) (actions.get("cut-end-of-line")), 1635 (Action) (actions.get("cut-word")), 1636 (Action) (actions.get("cut-end-of-word")), 1637 (Action) (actions.get(DefaultEditorKit.pasteAction)), 1638 (Action) (actions.get("indent")), 1639 (Action) (actions.get("de-indent")), 1640 (Action) (actions.get(DefaultEditorKit.insertTabAction)), 1641 (Action) (actions.get("new-line")), 1642 (Action) (actions.get(DefaultEditorKit.insertBreakAction)), 1643 (Action) (actions.get("insert-method")), 1644 (Action) (actions.get("comment-block")), 1645 (Action) (actions.get("uncomment-block")), 1646 (Action) (actions.get("indent-block")), 1647 (Action) (actions.get("deindent-block")), 1648 1649 (Action) (actions.get(DefaultEditorKit.selectWordAction)), (Action) (actions.get(DefaultEditorKit.selectLineAction)), 1651 (Action) (actions.get(DefaultEditorKit.selectParagraphAction)), 1652 (Action) (actions.get(DefaultEditorKit.selectAllAction)), 1653 (Action) (actions.get(DefaultEditorKit.selectionBackwardAction)), 1654 (Action) (actions.get(DefaultEditorKit.selectionForwardAction)), 1655 (Action) (actions.get(DefaultEditorKit.selectionUpAction)), 1656 (Action) (actions.get(DefaultEditorKit.selectionDownAction)), 1657 (Action) (actions.get(DefaultEditorKit.selectionBeginWordAction)), 1658 (Action) (actions.get(DefaultEditorKit.selectionEndWordAction)), 1659 (Action) (actions.get(DefaultEditorKit.selectionPreviousWordAction)), (Action) (actions.get(DefaultEditorKit.selectionNextWordAction)), 1661 (Action) (actions.get(DefaultEditorKit.selectionBeginLineAction)), 1662 (Action) (actions.get(DefaultEditorKit.selectionEndLineAction)), 1663 (Action) (actions.get(DefaultEditorKit.selectionBeginParagraphAction)), 1664 (Action) (actions.get(DefaultEditorKit.selectionEndParagraphAction)), 1665 (Action) (actions.get("selection-page-up")), 1666 (Action) (actions.get("selection-page-down")), 1667 (Action) (actions.get(DefaultEditorKit.selectionBeginAction)), 1668 (Action) (actions.get(DefaultEditorKit.selectionEndAction)), 1669 (Action) (actions.get("unselect")), 1670 1671 1673 (Action) (actions.get(DefaultEditorKit.backwardAction)), (Action) (actions.get(DefaultEditorKit.forwardAction)), 1675 (Action) (actions.get(DefaultEditorKit.upAction)), 1676 (Action) (actions.get(DefaultEditorKit.downAction)), 1677 (Action) (actions.get(DefaultEditorKit.beginWordAction)), 1678 (Action) (actions.get(DefaultEditorKit.endWordAction)), 1679 (Action) (actions.get(DefaultEditorKit.previousWordAction)), 1680 (Action) (actions.get(DefaultEditorKit.nextWordAction)), 1681 (Action) (actions.get(DefaultEditorKit.beginLineAction)), 1682 (Action) (actions.get(DefaultEditorKit.endLineAction)), (Action) (actions.get(DefaultEditorKit.beginParagraphAction)), 1684 (Action) (actions.get(DefaultEditorKit.endParagraphAction)), 1685 (Action) (actions.get(DefaultEditorKit.pageUpAction)), 1686 (Action) (actions.get(DefaultEditorKit.pageDownAction)), 1687 (Action) (actions.get(DefaultEditorKit.beginAction)), 1688 (Action) (actions.get(DefaultEditorKit.endAction)), 1689 1690 (Action) (actions.get("save")), (Action) (actions.get("reload")), 1693 (Action) (actions.get("close")), 1694 (Action) (actions.get("print")), 1695 (Action) (actions.get("page-setup")), 1696 1697 (Action) (actions.get("key-bindings")), (Action) (actions.get("preferences")), 1700 1701 (Action) (actions.get("describe-key")), (Action) (actions.get("help-mouse")), 1704 (Action) (actions.get("show-manual")), 1705 (Action) (actions.get("about-editor")), 1706 1707 undoAction, redoAction, 1710 (Action) (actions.get("find")), 1711 (Action) (actions.get("find-next")), 1712 (Action) (actions.get("find-next-backward")), 1713 (Action) (actions.get("replace")), 1714 (Action) (actions.get("compile")), 1715 (Action) (actions.get("toggle-interface-view")), 1716 (Action) (actions.get("toggle-breakpoint")), 1717 (Action) (actions.get("go-to-line")), 1718 }; 1720 categories = new String [] { 1721 Config.getString("editor.functions.editFunctions"), 1722 Config.getString("editor.functions.moveScroll"), Config.getString("editor.functions.classFunctions"), 1723 Config.getString("editor.functions.customisation"), Config.getString("editor.functions.help"), 1724 Config.getString("editor.functions.misc") 1725 }; 1726 1727 categoryIndex = new int[] { 0, 41, 57, 62, 64, 68, 78 }; 1728 } 1729 1730 1734 public void setDefaultKeyBindings() 1735 { 1736 keymap.removeBindings(); 1737 1738 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_MASK), 1739 (Action) (actions.get("save"))); 1740 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_P, SHORTCUT_MASK), 1742 (Action) (actions.get("print"))); 1743 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_W, SHORTCUT_MASK), (Action) (actions 1745 .get("close"))); 1746 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_Z, SHORTCUT_MASK), (Action) (actions 1747 .get("undo"))); 1748 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_Y, SHORTCUT_MASK), (Action) (actions 1749 .get("redo"))); 1750 keymap 1751 .addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_F8, 0), (Action) (actions 1752 .get("comment-block"))); 1753 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_F7, 0), (Action) (actions 1754 .get("uncomment-block"))); 1755 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_F6, 0), (Action) (actions.get("indent-block"))); 1756 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0), 1757 (Action) (actions.get("deindent-block"))); 1758 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_M, SHORTCUT_MASK), 1759 (Action) (actions.get("insert-method"))); 1760 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), 1761 (Action) (actions.get("indent"))); 1762 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, Event.SHIFT_MASK), 1763 (Action) (actions.get("de-indent"))); 1764 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_I, SHORTCUT_MASK), 1765 (Action) (actions.get("insert-tab"))); 1766 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), 1767 (Action) (actions.get("new-line"))); 1768 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, Event.SHIFT_MASK), 1769 (Action) (actions.get("insert-break"))); 1770 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_F, SHORTCUT_MASK), 1771 (Action) (actions.get("find"))); 1772 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_G, SHORTCUT_MASK), 1773 (Action) (actions.get("find-next"))); 1774 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_G, SHIFT_SHORTCUT_MASK), (Action) (actions 1775 .get("find-next-backward"))); 1776 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_R, SHORTCUT_MASK), (Action) (actions 1777 .get("replace"))); 1778 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_L, SHORTCUT_MASK), (Action) (actions 1779 .get("go-to-line"))); 1780 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_K, SHORTCUT_MASK), (Action) (actions 1781 .get("compile"))); 1782 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_J, SHORTCUT_MASK), (Action) (actions 1783 .get("toggle-interface-view"))); 1784 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_B, SHORTCUT_MASK), (Action) (actions 1785 .get("toggle-breakpoint"))); 1786 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_D, SHORTCUT_MASK), (Action) (actions 1790 .get("describe-key"))); 1791 1794 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_C, SHORTCUT_MASK), (Action) (actions 1795 .get(DefaultEditorKit.copyAction))); 1796 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_X, SHORTCUT_MASK), (Action) (actions 1797 .get(DefaultEditorKit.cutAction))); 1798 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_V, SHORTCUT_MASK), (Action) (actions 1799 .get(DefaultEditorKit.pasteAction))); 1800 1801 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), (Action) (actions.get("copy-line"))); 1803 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_F3, 0), (Action) (actions 1804 .get(DefaultEditorKit.pasteAction))); 1805 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_F4, 0), (Action) (actions.get("cut-line"))); 1806 1807 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_UP, ALT_SHORTCUT_MASK), (Action) (actions 1809 .get(DefaultEditorKit.pasteAction))); 1810 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, ALT_SHORTCUT_MASK), (Action) (actions 1811 .get(DefaultEditorKit.deletePrevCharAction))); 1812 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, ALT_SHORTCUT_MASK), (Action) (actions 1813 .get(DefaultEditorKit.deleteNextCharAction))); 1814 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, SHIFT_ALT_SHORTCUT_MASK), 1815 (Action) (actions.get("cut-line"))); 1816 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, SHIFT_ALT_SHORTCUT_MASK), 1817 (Action) (actions.get("cut-end-of-line"))); 1818 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, DOUBLE_SHORTCUT_MASK), (Action) (actions 1819 .get("cut-word"))); 1820 keymap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, DOUBLE_SHORTCUT_MASK), (Action) (actions 1821 .get("cut-end-of-word"))); 1822 } 1823 1824 1829 interface LineAction 1830 { 1831 1834 public void apply(Element line, MoeSyntaxDocument doc); 1835 } 1836 1837 1838 1839 1842 class CommentLineAction 1843 implements LineAction 1844 { 1845 1848 public void apply(Element line, MoeSyntaxDocument doc) 1849 { 1850 int lineStart = line.getStartOffset(); 1851 try { 1852 doc.insertString(lineStart, "// ", null); 1853 } 1854 catch (Exception exc) {} 1855 } 1856 } 1857 1858 1859 1863 class UncommentLineAction 1864 implements LineAction 1865 { 1866 public void apply(Element line, MoeSyntaxDocument doc) 1867 { 1868 int lineStart = line.getStartOffset(); 1869 int lineEnd = line.getEndOffset(); 1870 try { 1871 String lineText = doc.getText(lineStart, lineEnd - lineStart); 1872 if (lineText.trim().startsWith("//")) { 1873 int cnt = 0; 1874 while (lineText.charAt(cnt) != '/') 1875 cnt++; 1877 if (lineText.charAt(cnt + 2) == ' ') 1878 doc.remove(lineStart, cnt + 3); 1879 else 1880 doc.remove(lineStart, cnt + 2); 1881 } 1882 } 1883 catch (Exception exc) {} 1884 } 1885 } 1886 1887 1890 class IndentLineAction 1891 implements LineAction 1892 { 1893 public void apply(Element line, MoeSyntaxDocument doc) 1894 { 1895 int lineStart = line.getStartOffset(); 1896 try { 1897 doc.insertString(lineStart, spaces.substring(0, tabSize), null); 1898 } 1899 catch (Exception exc) {} 1900 } 1901 } 1902 1903 1907 class DeindentLineAction 1908 implements LineAction 1909 { 1910 public void apply(Element line, MoeSyntaxDocument doc) 1911 { 1912 int lineStart = line.getStartOffset(); 1913 int lineEnd = line.getEndOffset(); 1914 try { 1915 String lineText = doc.getText(lineStart, lineEnd - lineStart); 1916 String spacedTab = spaces.substring(0, tabSize); 1917 if (lineText.startsWith(spacedTab)) 1918 doc.remove(lineStart, tabSize); else if (lineText.charAt(0) == TAB_CHAR) 1920 doc.remove(lineStart, 1); else { 1922 int cnt = 0; 1923 while (lineText.charAt(cnt) == ' ') 1924 cnt++; 1926 doc.remove(lineStart, cnt); 1927 } 1928 } 1929 catch (Exception exc) {} 1930 } 1931 } 1932 1933 1937 class KeyCatcher extends KeyAdapter 1938 { 1939 MoeEditor editor; 1940 1941 public void keyPressed(KeyEvent e) 1942 { 1943 int keyCode = e.getKeyCode(); 1944 1945 if (keyCode == KeyEvent.VK_CAPS_LOCK || keyCode == KeyEvent.VK_SHIFT || keyCode == KeyEvent.VK_CONTROL || keyCode == KeyEvent.VK_META 1948 || keyCode == KeyEvent.VK_ALT || keyCode == KeyEvent.VK_ALT_GRAPH || keyCode == KeyEvent.VK_COMPOSE 1949 || keyCode == KeyEvent.VK_NUM_LOCK || keyCode == KeyEvent.VK_SCROLL_LOCK 1950 || keyCode == KeyEvent.VK_UNDEFINED) 1951 return; 1952 1953 KeyStroke key = KeyStroke.getKeyStrokeForEvent(e); 1954 String modifierName = KeyEvent.getKeyModifiersText(key.getModifiers()); 1955 String keyName = KeyEvent.getKeyText(keyCode); 1956 if (modifierName.length() > 0) 1957 keyName = modifierName + "+" + keyName; 1958 1959 Keymap map = keymap; 1960 Action action = null; 1961 1962 while (map != null && action == null) { 1963 action = map.getAction(key); 1964 map = map.getResolveParent(); 1965 } 1966 1967 if (action == null) { 1968 Object binding = componentInputMap.get(key); 1972 if (binding == null){ 1973 editor.writeMessage(keyName + Config.getString("editor.keypressed.keyIsNotBound")); 1975 } 1976 else { 1977 editor.writeMessage(keyName + Config.getString("editor.keypressed.callsTheFunction") + binding + "\""); 1978 } 1979 } 1980 else { 1981 String name = (String ) action.getValue(Action.NAME); 1982 editor.writeMessage(keyName + Config.getString("editor.keypressed.callsTheFunction") + name + "\""); 1983 } 1984 e.getComponent().removeKeyListener(keyCatcher); 1985 e.consume(); 1986 } 1987 1988 public void setEditor(MoeEditor ed) 1989 { 1990 editor = ed; 1991 } 1992 1993 } 1994 1995} | Popular Tags |