1 2 package org.objectweb.jac.aspects.gui.swing; 3 4 import java.awt.Color ; 5 import java.awt.Cursor ; 6 import java.awt.Dimension ; 7 import java.awt.Font ; 8 import java.awt.FontMetrics ; 9 import java.awt.Graphics ; 10 import java.awt.Rectangle ; 11 import java.awt.datatransfer.Clipboard ; 12 import java.awt.datatransfer.ClipboardOwner ; 13 import java.awt.datatransfer.DataFlavor ; 14 import java.awt.datatransfer.StringSelection ; 15 import java.awt.datatransfer.Transferable ; 16 import java.awt.event.FocusEvent ; 17 import java.awt.event.FocusListener ; 18 import java.awt.event.KeyEvent ; 19 import java.awt.event.KeyListener ; 20 import java.awt.event.MouseEvent ; 21 import java.awt.event.MouseListener ; 22 import java.awt.event.MouseMotionListener ; 23 import java.awt.event.TextEvent ; 24 import java.awt.event.TextListener ; 25 import java.io.BufferedInputStream ; 26 import java.io.BufferedReader ; 27 import java.io.File ; 28 import java.io.FileInputStream ; 29 import java.io.FileWriter ; 30 import java.io.IOException ; 31 import java.io.InputStreamReader ; 32 import java.io.PrintWriter ; 33 import java.util.HashSet ; 34 import java.util.Set ; 35 import java.util.Vector ; 36 import javax.swing.JPanel ; 37 import javax.swing.JScrollBar ; 38 import javax.swing.JScrollPane ; 39 import javax.swing.JViewport ; 40 import javax.swing.Scrollable ; 41 import javax.swing.SwingConstants ; 42 import javax.swing.event.CaretEvent ; 43 import javax.swing.event.CaretListener ; 44 import org.apache.log4j.Logger; 45 import org.objectweb.jac.util.Strings; 46 47 62 63 public class SHEditor extends JPanel 64 implements KeyListener , MouseListener , MouseMotionListener , 65 Scrollable , ClipboardOwner , FocusListener 66 { 67 static Logger logger = Logger.getLogger("gui.sheditor"); 68 static Logger loggerComp = Logger.getLogger("completion"); 69 static Logger loggerClip = Logger.getLogger("clipboard"); 70 71 private String text = ""; 72 private FontMetrics metrics; 73 int lineHeight; 75 private int caretPosition = 0; 76 private int selectionStart = 0; 77 private int selectionEnd = 0; 78 79 protected boolean isSelectionCompletion = false; 80 81 82 private int openPos = -1; 83 84 private int closePos = -1; 85 86 private int lineToMark = -1; 87 88 private boolean showCaret = true; 89 90 protected SHEditorConfig conf = new SHEditorConfig(); 91 public SHEditorConfig getConfig() { 92 return conf; 93 } 94 public void setConfig(SHEditorConfig conf) { 95 this.conf = conf; 96 } 97 98 public static final int DEFAULT = 0; 99 public static final int COMMENT = 1; 100 public static final int STRING = 2; 101 102 protected int syntaxUnderCaret; 103 public int getSyntaxUnderCaret() { 104 return syntaxUnderCaret; 105 } 106 107 private int mousePressPos = 0; 108 109 private Vector doneActions = new Vector (); 110 private Vector redoneActions = new Vector (); 111 112 private Rectangle car = new Rectangle (0, 0, 2, 0); 113 114 boolean changed = false; 115 116 private char separators[] = new char[] { 117 '\n', ' ', '.' , ',', '(', ')', '{', '}', '[', ']', '/', '-', '+', '*', 118 '<', '>', '=', ';', '"', '\'', '&', '|', '!' 119 }; 120 121 124 public void setWordSeparators(char[] separators) { 125 this.separators = separators; 126 } 127 128 131 public SHEditor() 132 { 133 super(); 134 135 setFont(new Font ("MonoSpaced", Font.PLAIN, 12)); 136 metrics = getFontMetrics(getFont()); 137 setCursor(new Cursor (Cursor.TEXT_CURSOR)); 138 addKeyListener(this); 139 addMouseListener(this); 140 addMouseMotionListener(this); 141 addFocusListener(this); 142 if (org.objectweb.jac.core.Jac.getMainJavaVersion().compareTo("1.4")>=0) { 143 setFocusTraversalKeysEnabled(false); 144 } 145 setBackground(Color.white); 146 } 147 148 152 public SHEditor(String txt) 153 { 154 this(); 155 text = txt; 156 } 157 158 162 public SHEditor(File file) 163 { 164 this(); 165 readFromFile(file); 166 } 167 168 Vector caretListeners = new Vector (); 169 176 public void addCaretListener(CaretListener listener) { 177 caretListeners.add(listener); 178 } 179 180 186 public void removeCaretListener(CaretListener listener) { 187 caretListeners.remove(listener); 188 } 189 190 protected void fireCaretUpdate() { 191 CaretEvent e = new MutableCaretEvent(this,caretPosition); 192 for (int i = caretListeners.size()-1; i>=0; i--) { 193 ((CaretListener )textListeners.get(i)).caretUpdate(e); 194 } 195 } 196 197 Vector textListeners = new Vector (); 198 199 206 public void addTextListener(TextListener listener) { 207 textListeners.add(listener); 208 } 209 210 216 public void removeTextListener(TextListener listener) { 217 textListeners.remove(listener); 218 } 219 220 protected void fireTextUpdate() { 221 TextEvent e = new TextEvent (this,TextEvent.TEXT_VALUE_CHANGED); 222 for (int i = textListeners.size()-1; i>=0; i--) { 223 ((TextListener )textListeners.get(i)).textValueChanged(e); 224 } 225 } 226 227 231 public String getText() 232 { 233 return text; 234 } 235 236 public void setText(String t) { 237 text=t; 238 fireTextUpdate(); 239 } 240 241 244 boolean eot() { 245 return caretPosition >= text.length(); 246 } 247 248 251 boolean endOfSelection() { 252 return caretPosition == selectionEnd; 253 } 254 255 258 boolean startOfSelection() { 259 return caretPosition == selectionStart; 260 } 261 262 266 public void setSelectionStart(int position) { 267 if (position>selectionEnd) { 268 int oldStart = selectionStart; 269 selectionStart = selectionEnd; 270 selectionEnd = position; 271 repaintChars(selectionStart,position); 272 } else { 273 repaintChars(selectionStart,position); 274 selectionStart = position; 275 } 276 } 277 278 282 public void setSelectionEnd(int position) { 283 if (position<selectionStart) { 284 int oldEnd = selectionEnd; 285 selectionEnd = selectionStart; 286 selectionStart = position; 287 repaintChars(selectionEnd,position); 288 } else { 289 repaintChars(selectionEnd,position); 290 selectionEnd = position; 291 } 292 } 293 294 299 public void setSelection(int start, int end) { 300 int oldStart = selectionStart; 301 int oldEnd = selectionEnd; 302 if (start<=end) { 303 selectionStart = start; 304 selectionEnd = end; 305 } else { 306 selectionStart = end; 307 selectionEnd = start; 308 } 309 repaintChars(oldStart,oldEnd); 310 repaintChars(selectionStart,selectionEnd); 311 } 312 313 317 void backwardMove(boolean select) { 318 if (select) { 319 if (caretPosition<selectionStart) 320 setSelectionStart(caretPosition); 321 else 322 setSelectionEnd(caretPosition); 323 } else { 324 resetSelection(); 325 } 326 } 327 328 332 void forwardMove(boolean select) { 333 if (select) { 334 if (caretPosition>selectionEnd) 335 setSelectionEnd(caretPosition); 336 else 337 setSelectionStart(caretPosition); 338 } else { 339 resetSelection(); 340 } 341 } 342 343 349 public void forwardChar(int n, boolean select) { 350 setCaretPosition(caretPosition + n); 351 forwardMove(select); 352 positionVisible(); 353 } 354 355 361 public void backwardChar(int n, boolean select) { 362 setCaretPosition(caretPosition - n); 363 backwardMove(select); 364 positionVisible(); 365 } 366 367 373 public void forwardWord(int n, boolean select) { 374 boolean endOfSelection = endOfSelection(); 375 int newPos = caretPosition; 376 while(!eot() && isDivider(text.charAt(newPos))) { 377 newPos++; 378 } 379 for (; n>0; n--) { 380 while(!eot() && !isDivider(text.charAt(newPos))) { 381 newPos++; 382 } 383 } 384 setCaretPosition(newPos); 385 forwardMove(select); 386 positionVisible(); 387 } 388 389 395 public void backwardWord(int n, boolean select) { 396 int newPos = caretPosition; 397 if (newPos>0) { 398 newPos--; 399 } 400 while (newPos>0 && isDivider(text.charAt(newPos))) { 401 newPos--; 402 } 403 for (; n>0; n--) { 404 while(newPos>0 && !isDivider(text.charAt(newPos))) { 405 newPos--; 406 } 407 } 408 if (!eot() && newPos>0) 409 newPos++; 410 setCaretPosition(newPos); 411 backwardMove(select); 412 positionVisible(); 413 } 414 415 421 public void nextLine(int n, boolean select) 422 { 423 boolean moved = false; 424 int newPos = caretPosition; 425 for (; n>0; n--) { 426 int posInLine = getPosInLine(newPos); 427 int nextLineStart = text.indexOf('\n', newPos); 428 if (nextLineStart != -1) 429 { 430 nextLineStart ++; 431 int i = 0; 432 while(i < posInLine && i + nextLineStart < text.length() && 433 text.charAt(i + nextLineStart) != '\n') 434 { 435 i ++; 436 } 437 if ((nextLineStart+i) >newPos) 438 moved = true; 439 newPos = nextLineStart + i; 440 } 441 } 442 if (moved) { 443 setCaretPosition(newPos); 444 forwardMove(select); 445 } 446 447 positionVisible(); 448 } 449 450 456 public void previousLine(int n, boolean select) 457 { 458 boolean moved = false; 459 int newPos = caretPosition; 460 for (; n>0; n--) { 461 int posInLine = getPosInLine(newPos); 462 int prevLineStart = 463 text.lastIndexOf('\n', newPos - posInLine - 2) + 1; 464 int i = 0; 465 while(i < posInLine && i + prevLineStart < text.length() && 466 text.charAt(i + prevLineStart) != '\n') 467 { 468 i ++; 469 } 470 if (prevLineStart+i<newPos) 471 moved = true; 472 newPos = prevLineStart+i; 473 } 474 if (moved) { 475 setCaretPosition(newPos); 476 backwardMove(select); 477 } 478 479 positionVisible(); 480 } 481 482 487 public void beginningOfText(boolean select) 488 { 489 setCaretPosition(0); 490 backwardMove(select); 491 positionVisible(); 492 } 493 494 495 500 public void endOfText(boolean select) 501 { 502 setCaretPosition(text.length()); 503 backwardMove(select); 504 positionVisible(); 505 } 506 507 512 public void beginningOfLine(boolean select) 513 { 514 int newPos = caretPosition; 515 if (getPosInLine(newPos) <= getWhiteAtLineStart(newPos)) { 516 newPos -= getPosInLine(newPos); 517 } else { 518 newPos -= 519 getPosInLine(newPos) - 520 getWhiteAtLineStart(newPos); 521 } 522 setCaretPosition(newPos); 523 backwardMove(select); 524 positionVisible(); 525 526 } 527 528 public void realBeginningOfLine(boolean select) 529 { 530 int newPos = caretPosition; 531 if (getPosInLine(newPos) <= getWhiteAtLineStart(newPos)) { 532 newPos -= getPosInLine(newPos); 533 } 534 setCaretPosition(newPos); 535 backwardMove(select); 536 positionVisible(); 537 } 538 539 544 public void endOfLine(boolean select) { 545 setCaretPosition(caretPosition + 546 getLineWidth(caretPosition) - getPosInLine(caretPosition)); 547 forwardMove(select); 548 positionVisible(); 549 } 550 551 555 public void gotoLine(int lineNumber) { 556 beginningOfText(false); 557 if (lineNumber>1) { 558 nextLine(lineNumber-1,false); 559 } 560 } 561 562 565 void resetSelection() { 566 int oldStart = selectionStart; 567 int oldEnd = selectionEnd; 568 selectionEnd = caretPosition; 569 selectionStart = caretPosition; 570 for (int p=oldStart; p<oldEnd; p++) 571 repaintCharAt(p); 572 } 573 574 577 void selectWord(int position) { 578 int oldStart = selectionStart; 579 int oldEnd = selectionEnd; 580 581 selectionEnd = caretPosition; 582 selectionStart = caretPosition; 583 while (selectionEnd<text.length() 584 && Character.isLetterOrDigit(text.charAt(selectionEnd))) { 585 selectionEnd++; 586 } 587 while (selectionStart>=0 && selectionStart<text.length() && 588 Character.isLetterOrDigit(text.charAt(selectionStart))) { 589 selectionStart--; 590 } 591 if (selectionStart>=0 && selectionStart<text.length() && 592 !Character.isLetterOrDigit(text.charAt(selectionStart))) 593 selectionStart++; 594 595 for (int p=oldStart; p<oldEnd; p++) 596 repaintCharAt(p); 597 } 598 599 CompletionEngine completionEngine; 600 601 public void setCompletionEngine(CompletionEngine ce) { 602 completionEngine = ce; 603 } 604 605 public CompletionEngine getCompletionEngine() { 606 return completionEngine; 607 } 608 609 void runCompletionEngine(int direction) { 610 611 if (completionEngine!=null) { 612 613 String writtenText = ""; 614 int pos; 615 if (selectionStart!=selectionEnd) { 616 pos = selectionStart; 617 } else { 618 pos = caretPosition; 619 } 620 int beginWritten = pos; 621 StringBuffer currentProposal = new StringBuffer (); 622 if (pos>0 && !isDivider(text.charAt(pos-1))) { 624 loggerComp.debug("written word found"); 625 beginWritten--; 626 while (beginWritten>0 && !isDivider(text.charAt(beginWritten-1))) { 628 beginWritten--; 629 } 630 writtenText = text.substring(beginWritten, pos); 631 if (selectionStart!=selectionEnd) { 632 currentProposal.append(writtenText); 633 } 634 } 635 636 currentProposal.append(text.substring(selectionStart, selectionEnd)); 637 int initPosition = caretPosition; 638 639 initPosition = selectionStart; 641 remove(selectionStart, selectionEnd - selectionStart); 642 resetSelection(); 643 isSelectionCompletion = true; 644 645 String proposedText = 646 completionEngine.getProposal( 647 text,beginWritten,writtenText, 648 currentProposal.toString(), 649 direction); 650 if (proposedText.length()>0) { 651 insertString(caretPosition,proposedText.substring(writtenText.length())); 652 } 653 654 setSelectionStart(initPosition); 655 setSelectionEnd(caretPosition); 656 657 } 658 } 659 660 KeyListener toolKeyListener; 661 public void toolDone() { 662 toolKeyListener = null; 663 } 664 665 668 public void keyPressed(KeyEvent e) 669 { 670 if (toolKeyListener!=null) { 671 toolKeyListener.keyPressed(e); 672 return; 673 } 674 if (e.isControlDown()) 675 { 676 switch (e.getKeyCode()) { 677 case KeyEvent.VK_C: 678 copy(); 679 break; 680 case KeyEvent.VK_V: 681 paste(); 682 break; 683 case KeyEvent.VK_X: 684 cut(); 685 break; 686 case KeyEvent.VK_Z: 687 undo(); 688 break; 689 case KeyEvent.VK_Y: 690 redo(); 691 break; 692 case KeyEvent.VK_S: 693 toolKeyListener = new SearchTool(this,caretPosition); 694 break; 695 case KeyEvent.VK_RIGHT: 696 forwardWord(1, e.isShiftDown()); 697 break; 698 case KeyEvent.VK_LEFT: 699 backwardWord(1, e.isShiftDown()); 700 break; 701 case KeyEvent.VK_HOME: 702 beginningOfText(e.isShiftDown()); 703 break; 704 case KeyEvent.VK_END: 705 endOfText(e.isShiftDown()); 706 break; 707 case KeyEvent.VK_SPACE: 708 runCompletionEngine( 709 e.isShiftDown()?CompletionEngine.BACKWARD:CompletionEngine.FORWARD); 710 break; 711 default: 712 } 713 } 714 else if ((e.getModifiers() & KeyEvent.ALT_MASK) > 0) 715 { 716 } 717 else if ((e.getModifiers() & KeyEvent.ALT_GRAPH_MASK) > 0) 718 { 719 } 720 else if (e.isShiftDown()) 721 { 722 switch (e.getKeyCode()) { 723 case KeyEvent.VK_LEFT: 724 backwardChar(1,e.isShiftDown()); 725 e.consume(); 726 break; 727 case KeyEvent.VK_RIGHT: 728 forwardChar(1,e.isShiftDown()); 729 e.consume(); 730 break; 731 case KeyEvent.VK_UP: 732 previousLine(1,e.isShiftDown()); 733 e.consume(); 734 break; 735 case KeyEvent.VK_DOWN: 736 nextLine(1,e.isShiftDown()); 737 e.consume(); 738 break; 739 case KeyEvent.VK_HOME: 740 beginningOfLine(e.isShiftDown()); 741 e.consume(); 742 break; 743 case KeyEvent.VK_END: 744 endOfLine(e.isShiftDown()); 745 e.consume(); 746 break; 747 case KeyEvent.VK_PAGE_UP: 748 previousLine(15,e.isShiftDown()); 749 e.consume(); 750 break; 751 case KeyEvent.VK_PAGE_DOWN: 752 nextLine(15,e.isShiftDown()); 753 e.consume(); 754 break; 755 case KeyEvent.VK_TAB: 756 { 757 if (selectionStart != selectionEnd) 758 { 759 int start = selectionStart; 760 int end = selectionEnd; 761 762 for(int pos = end; 763 pos >= start - getPosInLine(start) && pos >= 0; 764 pos--) 765 { 766 if (pos == 0 || text.charAt(pos - 1) == '\n') 767 { 768 for(int i=0; 769 i < conf.getTabWidth() && text.charAt(pos) == ' '; 770 i++) 771 { 772 remove(pos, 1); 773 end--; 774 } 775 } 776 } 777 setSelection(start,end); 778 } 779 else 780 { 781 } 782 e.consume(); 783 } 784 break; 785 default: 786 } 787 } 788 else 789 { 790 switch (e.getKeyCode()) { 791 case KeyEvent.VK_LEFT: 792 backwardChar(1,e.isShiftDown()); 793 e.consume(); 794 break; 795 case KeyEvent.VK_RIGHT: 796 forwardChar(1,e.isShiftDown()); 797 e.consume(); 798 break; 799 case KeyEvent.VK_UP: 800 previousLine(1,e.isShiftDown()); 801 e.consume(); 802 break; 803 case KeyEvent.VK_DOWN: 804 nextLine(1,e.isShiftDown()); 805 e.consume(); 806 break; 807 case KeyEvent.VK_TAB: 808 if (selectionStart == selectionEnd) 809 { 810 insertTab(caretPosition); 811 } 812 else 813 { 814 int start = selectionStart; 815 int end = selectionEnd; 816 817 for(int pos=end; 818 pos>=start-getPosInLine(start) && pos>=0; 819 pos--) 820 { 821 if (pos == 0 || text.charAt(pos - 1) == '\n') 822 { 823 end += conf.getTabWidth(); 824 insertTab(pos); 825 } 826 } 827 setSelection(start,end); 828 } 829 e.consume(); 830 break; 831 case KeyEvent.VK_DELETE: 832 if (selectionStart == selectionEnd) 833 { 834 if (caretPosition < text.length()) { 835 remove(caretPosition, 1); 836 } 837 } 838 else 839 { 840 remove(selectionStart, selectionEnd - selectionStart); 841 } 842 resetSelection(); 843 positionVisible(); 844 e.consume(); 845 break; 846 case KeyEvent.VK_HOME: 847 beginningOfLine(e.isShiftDown()); 848 e.consume(); 849 break; 850 case KeyEvent.VK_END: 851 endOfLine(e.isShiftDown()); 852 e.consume(); 853 break; 854 case KeyEvent.VK_PAGE_UP: 855 previousLine(15,e.isShiftDown()); 856 e.consume(); 857 break; 858 case KeyEvent.VK_PAGE_DOWN: 859 nextLine(15,e.isShiftDown()); 860 e.consume(); 861 break; 862 default: 863 e.consume(); 864 } 865 } 866 } 867 868 871 public void keyTyped(KeyEvent e) 872 { 873 if (toolKeyListener!=null) { 874 toolKeyListener.keyTyped(e); 875 return; 876 } 877 if (e.isControlDown()) 878 { 879 } 880 else if ((e.getModifiers() & KeyEvent.ALT_MASK) > 0) 881 { 882 } 883 else 884 { 885 switch (e.getKeyChar()) { 886 case KeyEvent.VK_TAB: 887 case KeyEvent.VK_DELETE: 888 e.consume(); 889 break; 890 case KeyEvent.VK_BACK_SPACE: 891 if (selectionStart == selectionEnd && caretPosition > 0) 892 { 893 remove(caretPosition - 1, 1); 894 resetSelection(); 895 } 896 else 897 { 898 remove(selectionStart, selectionEnd - selectionStart); 899 resetSelection(); 900 } 901 e.consume(); 902 break; 903 case KeyEvent.VK_ENTER: 904 { 905 if (selectionStart != selectionEnd) 906 remove(selectionStart, selectionEnd - selectionStart); 907 insertReturn(); 908 e.consume(); 909 } 910 break; 911 case '}': 912 { 913 if (selectionStart != selectionEnd) 914 remove(selectionStart, selectionEnd - selectionStart); 915 insertCloseCBracket(); 916 } 917 break; 918 default: 919 if (selectionStart != selectionEnd && 920 (!isSelectionCompletion || !isAcceptCompletionChar(e.getKeyChar()))) 921 remove(selectionStart, selectionEnd - selectionStart); 922 isSelectionCompletion = false; 923 insertChar(e.getKeyChar()); 924 if (!isDivider(e.getKeyChar()) && conf.isAutoComplete() && 926 syntaxUnderCaret!=COMMENT && syntaxUnderCaret!=STRING && 927 (eot() || isDivider(text.charAt(caretPosition)))) { 928 runCompletionEngine(CompletionEngine.FORWARD); 929 } else if (completionEngine!=null && 930 completionEngine.isAutomaticCompletionChar(e.getKeyChar())) 931 { 932 int i=caretPosition; 933 completionEngine.runAutomaticCompletion( 934 this,text,caretPosition,e.getKeyChar()); 935 caretPosition=i; 936 } 937 positionVisible(); 939 } 940 } 941 } 942 943 946 boolean isAcceptCompletionChar(char c) { 947 return isDivider(c) || c=='.'; 948 } 949 950 954 public void insertCloseCBracket() { 955 int white = getWhiteAtLineStart(caretPosition); 956 int lineWidth = getLineWidth(caretPosition); 957 int posInLine = getPosInLine(caretPosition); 958 int neededWhite = 0; 959 960 int count = 1; 961 int pos = getCaretPosition() - 1; 962 963 if (pos > 0) 964 { 965 do 966 { 967 if (text.charAt(pos) == '}') 968 count ++; 969 else if (text.charAt(pos) == '{') 970 count --; 971 972 if (count != 0) 973 pos --; 974 } 975 while (pos > -1 && count > 0); 976 } 977 978 if (pos==text.length()-1 || text.charAt(pos+1)!='\n') { 980 insertChar('}'); 981 return; 982 } 983 984 while (pos > 0 && text.charAt(pos - 1) != '\n') 986 { 987 neededWhite ++; 988 pos --; 989 if(text.charAt(pos)!=' ') neededWhite=0; 990 } 991 992 if (white == posInLine && white > neededWhite) 993 { 994 remove(caretPosition - posInLine + neededWhite, 995 white - neededWhite); 996 insertChar('}'); 997 } 998 else if (white == posInLine) 999 { 1000 insertChar('}'); 1001 } 1002 else 1003 { 1004 insertChar('\n'); 1005 for(int i=0; i<neededWhite; i++) 1006 insertChar(' '); 1007 insertChar('}'); 1008 } 1009 } 1010 1011 1015 public void insertReturn() { 1016 int white = 0; 1017 if (caretPosition==text.length() || text.charAt(caretPosition)=='\n') { 1018 white = getWhiteAtLineStart(selectionStart); 1019 if (selectionStart > 0 && text.charAt(selectionStart - 1) == '{') { 1020 white += 4; 1021 } 1022 } else { 1023 int savedCaret = caretPosition; 1024 int white2 = getWhiteAtLineStart(caretPosition); 1025 realBeginningOfLine(false); 1026 if (caretPosition>0) { 1027 white = getWhiteAtLineStart(caretPosition-1) - white2; 1028 if (savedCaret - caretPosition<=white2) 1029 white += savedCaret - caretPosition; 1030 } 1031 caretPosition = savedCaret; 1032 } 1033 String ins = "" + '\n'; 1034 for(int i=0; i<white; i++) ins += " "; 1035 insertString(caretPosition, ins); 1036 } 1037 1038 1042 void insertTab(int pos) 1043 { 1044 insertString(pos, Strings.newString(' ',conf.getTabWidth())); 1045 } 1046 1047 1050 public void keyReleased(KeyEvent e) 1051 { 1052 testOposing(); 1053 } 1054 1055 1060 int getPosInLine(int pos) 1061 { 1062 int ret = text.lastIndexOf('\n', pos - 1); 1063 ret ++; 1064 ret = pos - ret; 1065 return ret; 1066 } 1067 1068 1073 int getLineWidth(int pos) 1074 { 1075 int start = 0; 1076 int end = text.indexOf('\n', pos); 1077 if (pos > 0) { 1078 start = text.lastIndexOf('\n',pos-1) + 1; 1079 } 1080 1081 if (end == -1) 1082 end = text.length(); 1083 1084 return end - start; 1085 } 1086 1087 1088 1093 String getLineText(int pos) 1094 { 1095 int start = 0; 1096 int end = text.indexOf('\n', pos); 1097 if (pos > 0) { 1098 start = text.lastIndexOf('\n', pos-1) + 1; 1099 } 1100 1101 if (end == -1) 1102 end = text.length(); 1103 1104 return text.substring(start,end); 1105 } 1106 1107 1112 int getWhiteAtLineStart(int pos) 1113 { 1114 int ret = 0; 1115 1116 for(int i = pos - getPosInLine(pos); 1117 i >= 0 && i < text.length() && text.charAt(i) == ' '; 1118 i++) 1119 { 1120 ret ++; 1121 } 1122 1123 return ret; 1124 } 1125 1126 1129 void insertChar(char c) 1130 { 1131 changed = true; 1132 doneActions.add(0, new TextAction(TextAction.INSERT, caretPosition, 1, "")); 1133 text = text.substring(0, caretPosition) + c + 1134 text.substring(caretPosition, text.length()); 1135 caretPosition ++; 1136 resetSelection(); 1137 1138 fireTextUpdate(); 1139 repaint(); 1140 positionVisible(); 1141 } 1142 1143 1148 public void insertString(int pos, String str) 1149 { 1150 changed = true; 1151 doneActions.add(0, new TextAction(TextAction.INSERT, pos, str.length(), "")); 1152 text = text.substring(0, pos) + str + text.substring(pos, text.length()); 1153 if (caretPosition >= pos) 1154 { 1155 caretPosition += str.length(); 1156 resetSelection(); 1157 } 1158 fireTextUpdate(); 1159 repaint(); 1160 positionVisible(); 1161 } 1162 1163 1168 public void remove(int offset, int length) 1169 { 1170 changed = true; 1171 if (offset >= 0 && offset + length <= text.length()) 1172 { 1173 doneActions.add( 1174 0, 1175 new TextAction(TextAction.REMOVE, offset, length, 1176 text.substring(offset, offset + length))); 1177 1178 text = text.substring(0,offset) + text.substring(offset+length,text.length()); 1179 if (caretPosition > offset && caretPosition <= offset + length) 1180 { 1181 setCaretPosition(offset); 1182 } 1183 else if (caretPosition > offset) 1184 { 1185 setCaretPosition(caretPosition-length); 1186 } 1187 repaint(); 1188 fireTextUpdate(); 1189 positionVisible(); 1190 } 1191 } 1192 1193 1196 public void undo() 1197 { 1198 if (doneActions.size() > 0) 1199 { 1200 changed = true; 1201 TextAction ta = (TextAction)doneActions.remove(0); 1202 try 1203 { 1204 if (ta.action == TextAction.INSERT) { 1205 redoneActions.add( 1206 0, 1207 new TextAction(TextAction.REMOVE, 1208 ta.position, 1209 ta.length, 1210 text.substring(ta.position, ta.position + ta.length))); 1211 text = text.substring(0, ta.position) + 1212 text.substring(ta.position + ta.length, text.length()); 1213 } else if (ta.action == TextAction.REMOVE) { 1214 redoneActions.add( 1215 0, 1216 new TextAction(TextAction.INSERT, ta.position, ta.length, "")); 1217 text = text.substring(0, ta.position) + ta.string + 1218 text.substring(ta.position, text.length()); 1219 } 1220 caretPosition = ta.position; 1221 } 1222 catch(Exception e) 1223 { 1224 } 1225 fireTextUpdate(); 1226 repaint(); 1227 } 1228 } 1229 1230 1233 public void redo() 1234 { 1235 if (redoneActions.size() > 0) 1236 { 1237 changed = true; 1238 TextAction ta = (TextAction)redoneActions.remove(0); 1239 try 1240 { 1241 if (ta.action == TextAction.INSERT) 1242 { 1243 doneActions.add( 1244 0, 1245 new TextAction( 1246 TextAction.REMOVE, ta.position, ta.length, 1247 text.substring(ta.position, ta.position + ta.length))); 1248 text = text.substring(0, ta.position) + 1249 text.substring(ta.position + ta.length, text.length()); 1250 } 1251 else 1252 { 1253 doneActions.add( 1254 0, 1255 new TextAction(TextAction.INSERT, ta.position, ta.length, "")); 1256 text = text.substring(0, ta.position) + 1257 ta.string + text.substring(ta.position, text.length()); 1258 } 1259 caretPosition = ta.position; 1260 } 1261 catch(Exception e) 1262 { 1263 } 1264 fireTextUpdate(); 1265 repaint(); 1266 } 1267 } 1268 1269 1274 int getLine(int pos) 1275 { 1276 int ret = 0; 1277 1278 int brPos = 0; 1279 boolean done = false; 1280 1281 while (brPos != -1 && !done) 1282 { 1283 brPos = text.indexOf('\n', brPos); 1284 1285 if (pos <= brPos) 1286 { 1287 done = true; 1288 } 1289 } 1290 return ret; 1291 } 1292 1293 1296 public void cut() 1297 { 1298 if (selectionStart != selectionEnd) 1299 { 1300 try 1301 { 1302 Clipboard clipboard = getToolkit().getSystemClipboard(); 1303 String post = text.substring(selectionStart, selectionEnd); 1304 clipboard.setContents(new StringSelection (post), this); 1305 remove(selectionStart,selectionEnd-selectionStart); 1306 resetSelection(); 1307 setCaretPosition(selectionStart); 1308 positionVisible(); 1309 } 1310 catch(Exception e) 1311 { 1312 } 1313 } 1314 } 1315 1316 1319 public void copy() 1320 { 1321 if (selectionStart != selectionEnd) 1322 { 1323 try 1324 { 1325 Clipboard clipboard = getToolkit().getSystemClipboard(); 1326 String post = text.substring(selectionStart, selectionEnd); 1327 clipboard.setContents(new StringSelection (post), this); 1328 } 1329 catch(Exception e) 1330 { 1331 } 1332 } 1333 } 1334 1335 1338 public void paste() 1339 { 1340 loggerClip.debug("paste..."); 1341 if (selectionStart != selectionEnd) 1342 { 1343 remove(selectionStart,selectionEnd-selectionStart); 1344 resetSelection(); 1345 setCaretPosition(selectionStart); 1346 } 1347 Clipboard clipboard = getToolkit().getSystemClipboard(); 1348 Transferable content = clipboard.getContents(this); 1349 if (content != null) 1350 { 1351 try 1352 { 1353 insertString(caretPosition, 1354 (String )content.getTransferData(DataFlavor.stringFlavor)); 1355 } 1356 catch (Exception e) 1357 { 1358 loggerClip.error("error in copying",e); 1359 } 1360 } else { 1361 loggerClip.debug("content is null"); 1362 } 1363 fireTextUpdate(); 1364 } 1365 1366 1372 public int countChar(char c, int offset, int length) 1373 { 1374 int ret = 0; 1375 for (int i=offset; i < offset+length; i++) { 1376 if (text.charAt(i) == c) 1377 ret ++; 1378 } 1379 return c; 1380 } 1381 1382 public void repaint() { 1383 super.repaint(); 1384 } 1386 1387 int getCharWidth(char c) { 1388 if (Character.isDefined(c)) 1389 return metrics.charWidth(c); 1390 else 1391 return 0; 1392 } 1393 1394 1398 public void paintComponent(Graphics g) 1399 { 1400 super.paintComponent(g); 1401 1402 g.setFont(getFont()); 1403 lineHeight = metrics.getHeight(); 1404 1405 Rectangle rect = getVisibleRect(); 1406 logger.debug("SHEditor.paintComponent on "+rect+" / "+g.getClip()); 1407 rect = g.getClipBounds(); 1408 1409 g.setColor(conf.getBackgroundColor()); 1410 g.fillRect(rect.x + getMarginLeft(), rect.y, 1411 rect.width - getMarginLeft(), rect.height); 1412 g.setColor(new Color (180, 180, 180)); 1413 g.fillRect(rect.x, rect.y, getMarginLeft(), rect.height); 1414 1415 int line = 1; 1416 int pos = 0; 1417 boolean done = false; 1418 boolean ignore = false; 1419 1420 StringBuffer word = new StringBuffer (); 1422 int posXStart = getMarginLeft(); 1423 int posX = posXStart; 1424 int maxPosX = posX; 1425 int posY = lineHeight; 1426 1427 while(posY + lineHeight < rect.y) 1429 { 1430 posY += lineHeight; 1431 if (pos + 1 < text.length()) { 1432 pos = text.indexOf("\n", pos); 1433 pos ++; 1434 line ++; 1435 } else { 1436 break; 1437 } 1438 } 1439 1440 if (text.lastIndexOf("/ *", pos) > text.lastIndexOf("* /", pos)) 1441 { 1442 int lastPos = text.lastIndexOf("/*", pos); 1443 int posInLine = getPosInLine(lastPos); 1444 int count = countChar('"', lastPos - posInLine, posInLine); 1445 ignore = (count%2 == 0); 1446 } 1447 1448 syntaxUnderCaret = DEFAULT; 1449 while (pos < text.length()) 1450 { 1451 done = false; 1452 g.setColor(conf.getTextColor()); 1453 1454 if (ignore) 1455 { 1456 word.append(text.charAt(pos)); 1457 pos ++; 1458 1459 while (pos < text.length() && !done) 1460 { 1461 if (text.charAt(pos) == '/' && text.charAt(pos - 1) == '*') { 1462 done = true; 1463 } 1464 word.append(text.charAt(pos)); 1465 pos ++; 1466 } 1467 } 1468 else if (word.length() == 0 && text.charAt(pos) == '"') 1470 { 1471 int startp = pos; 1472 word.append(text.charAt(pos)); 1473 pos ++; 1474 1475 while (pos < text.length() && !done) 1476 { 1477 if (text.charAt(pos) == '"') { 1478 if (text.charAt(pos - 1) != '\\' || 1479 text.charAt(pos - 2) == '\\') 1480 { 1481 done = true; 1482 } 1483 } else if (text.charAt(pos) == '\n') { 1484 done = true; 1486 } 1487 1488 word.append(text.charAt(pos)); 1489 pos ++; 1490 } 1491 if (caretPosition<pos && caretPosition>startp) 1492 syntaxUnderCaret = STRING; 1493 g.setColor(conf.getStringColor()); 1494 } 1495 else if (word.length() == 0 && text.charAt(pos) == '\'') 1497 { 1498 int startp = pos; 1499 word.append(text.charAt(pos)); 1500 pos ++; 1501 1502 while (pos < text.length() && !done) 1503 { 1504 if (text.charAt(pos) == '\'') { 1505 if (text.charAt(pos - 1) != '\\' || 1506 text.charAt(pos - 2) == '\\') 1507 { 1508 done = true; 1509 } 1510 } else if (text.charAt(pos) == '\n') { 1511 done = true; 1513 } 1514 1515 word.append(text.charAt(pos)); 1516 pos ++; 1517 } 1518 if (caretPosition<pos && caretPosition>startp) 1519 syntaxUnderCaret = STRING; 1520 g.setColor(conf.getStringColor()); 1521 } 1522 else if (text.charAt(pos) == '/' && 1524 pos < text.length() - 1 && 1525 text.charAt(pos + 1) == '/' && 1526 (pos == 0 || text.charAt(pos - 1) != '*')) 1527 { 1528 int startp = pos; 1529 word.append(text.charAt(pos)); 1530 pos ++; 1531 1532 while (pos < text.length() && !done) 1533 { 1534 if (text.charAt(pos) == '\n') { 1535 done = true; 1536 } 1537 word.append(text.charAt(pos)); 1538 pos ++; 1539 } 1540 if (caretPosition<=pos && caretPosition>startp) 1541 syntaxUnderCaret = COMMENT; 1542 g.setColor(conf.getIgnoreColor()); 1543 } 1544 else if (text.charAt(pos) == '/' && 1546 pos < text.length() - 1 && 1547 text.charAt(pos + 1) == '*' && 1548 (pos == 0 || text.charAt(pos - 1) != '/')) 1549 { 1550 int startp = pos; 1551 word.append(text.charAt(pos)); 1552 pos ++; 1553 1554 while (pos < text.length() && !done) 1555 { 1556 if (text.charAt(pos) == '/' && 1557 text.charAt(pos - 1) == '*') 1558 { 1559 done = true; 1560 } 1561 word.append(text.charAt(pos)); 1562 pos ++; 1563 } 1564 if (caretPosition<pos && caretPosition>startp) 1565 syntaxUnderCaret = COMMENT; 1566 g.setColor(conf.getIgnoreColor()); 1567 } 1568 else if (isDivider(text.charAt(pos))) 1570 { 1571 if (word.length() == 0) { 1572 word.append(text.charAt(pos)); 1573 pos ++; 1574 } 1575 done = true; 1576 } 1577 else 1579 { 1580 while (pos < text.length() && !done) 1581 { 1582 if (isDivider(text.charAt(pos))) { 1583 done = true; 1584 } else { 1585 word.append(text.charAt(pos)); 1586 pos ++; 1587 } 1588 } 1589 if (isKeyword(word.toString())) { 1590 g.setColor(conf.getKeywordColor()); 1591 } else if (isModifier(word.toString())) { 1592 g.setColor(conf.getModifierColor()); 1593 } else if (isType(word.toString())) { 1594 g.setColor(conf.getTypeColor()); 1595 } else { 1596 g.setColor(conf.getTextColor()); 1597 } 1598 } 1599 1600 if (ignore) { 1601 g.setColor(conf.getIgnoreColor()); 1602 ignore = false; 1603 } else if (word.toString().equals("{") || 1604 word.toString().equals("}")) { 1605 g.setColor(conf.getClampColor()); 1606 } 1607 1608 for(int i=0; i<word.length(); i++) 1609 { 1610 char c = word.charAt(i); 1611 int charWidth = getCharWidth(c); 1612 1613 if (posY + lineHeight > rect.y && 1614 pos == openPos + 1 || pos == closePos + 1) 1615 { 1616 Color tmpColor = g.getColor(); 1618 g.setColor(Color.pink); 1619 if (posX >= rect.x && posX < rect.x + rect.width) 1620 g.fillRect(posX, posY - metrics.getAscent(), 1621 charWidth, 1622 metrics.getAscent()); 1623 g.setColor(tmpColor); 1624 } 1625 else if (posY + lineHeight > rect.y && 1626 pos - word.length() + i < selectionEnd && 1627 pos - word.length() + i >= selectionStart) 1628 { 1629 Color tmpColor = g.getColor(); 1631 g.setColor(isSelectionCompletion ? 1632 conf.getCompletionColor() : conf.getSelectionColor()); 1633 if (posX >= rect.x && posX < rect.x + rect.width) 1634 g.fillRect(posX, posY - metrics.getAscent(), 1635 charWidth, 1636 metrics.getAscent()); 1637 g.setColor(tmpColor); 1638 } 1639 1640 if (posY + lineHeight > rect.y && 1641 hasFocus() && 1642 showCaret && 1643 caretPosition == pos - word.length() + i) 1644 { 1645 car.x = posX; 1646 car.y = posY - lineHeight; 1647 car.height = lineHeight; 1648 } 1649 if (c == '\n') 1650 { 1651 Color tmpColor = g.getColor(); 1652 g.setColor(new Color (180, 180, 180)); 1653 g.fillRect(rect.x, posY - lineHeight, 1654 getMarginLeft(), lineHeight); 1655 g.setColor(new Color (200, 0, 0)); 1656 g.drawString( 1657 "" + line, 1658 rect.x + (getMarginLeft()-10) 1659 - metrics.charsWidth(("" + line).toCharArray(), 1660 0, ("" + line).length()), 1661 posY - metrics.getDescent()); 1662 1663 if (lineToMark == line) 1664 { 1665 g.setColor(Color.green); 1666 g.fillPolygon( 1667 new int[] { rect.x + 58, rect.x + 63, rect.x + 58 }, 1668 new int[] { posY - (int)(lineHeight / 1.5d), 1669 posY - (int)(lineHeight / 3d), 1670 posY }, 1671 3); 1672 } 1673 g.setColor(tmpColor); 1674 1675 posY += lineHeight; 1676 posX = posXStart; 1677 line ++; 1678 } 1679 else if (c == '\t') 1680 { 1681 posX += getCharWidth(' ') * conf.getTabWidth(); 1682 } 1683 else if (charWidth > 0 && posY + lineHeight > rect.y) 1684 { 1685 if ((posX+charWidth) >= rect.x && posX < rect.x + rect.width) 1686 g.drawString("" + c, posX, posY - metrics.getDescent()); 1687 posX += charWidth; 1688 } 1689 } 1690 1691 if (posX > maxPosX) { 1692 maxPosX = posX; 1693 } 1694 1695 if (posY - lineHeight > rect.y + rect.height) 1697 { 1698 for(int p = pos; p != -1; p = text.indexOf('\n', p + 1)) 1699 { 1700 posY += lineHeight; 1701 1702 int width = getPixelTextWidth(getLineText(p)); 1703 if (width > maxPosX) { 1704 maxPosX = width; 1705 } 1706 } 1707 1708 pos = text.length(); 1709 } 1710 1711 word.delete(0, word.length()); 1712 } 1713 1714 if (conf.getShowLineNumbers() && 1715 (posY - lineHeight <= rect.y + rect.height)) 1716 { 1717 g.setColor(conf.getLineNrBgColor()); 1718 g.fillRect(rect.x, posY - lineHeight, 1719 getMarginLeft(), lineHeight); 1720 g.setColor(conf.getLineNrColor()); 1721 g.drawString("" + line, 1722 rect.x + (getMarginLeft()-10) 1723 - metrics.charsWidth(("" + line).toCharArray(), 1724 0, ("" + line).length()), 1725 posY - metrics.getDescent()); 1726 1727 if (lineToMark == line) 1728 { 1729 g.setColor(Color.green); 1730 g.fillPolygon( 1731 new int[] { rect.x + 58, rect.x + 63, rect.x + 58 }, 1732 new int[] { posY - (int)(lineHeight / 1.5d), 1733 posY - (int)(lineHeight / 3d), 1734 posY }, 1735 3); 1736 } 1737 } 1738 1739 if (hasFocus() && 1740 posY - lineHeight <= rect.y + rect.height && 1741 showCaret && pos == text.length() && 1742 pos == caretPosition) 1743 { 1744 car.x = posX; 1745 car.y = posY - lineHeight; 1746 car.height = lineHeight; 1747 } 1748 1749 if (hasFocus()) 1750 g.setColor(Color.black); 1751 else 1752 g.setColor(Color.gray); 1753 g.fillRect(car.x, car.y, car.width, car.height); 1754 1755 if (posY + 10 != getSize().height || maxPosX + 10 != getSize().width) 1756 { 1757 setMinimumSize( 1758 new Dimension ( 1759 (maxPosX+10 > getSize().width ? maxPosX+10 : getSize().width), 1760 posY+10)); 1761 setPreferredSize( 1762 new Dimension (maxPosX+10,posY+10)); 1763 logger.debug("revalidate"); 1764 revalidate(); 1765 } 1766 } 1767 1768 1773 protected int getPixelTextWidth(String text) { 1774 int width = 0; 1775 for (int i=0; i<text.length(); i++) { 1776 if (text.charAt(i)==KeyEvent.VK_TAB) 1777 width += getCharWidth(' ') * conf.getTabWidth(); 1778 else 1779 width += getCharWidth(text.charAt(i)); 1780 1781 } 1782 return width; 1783 } 1784 1785 1788 public void update(Graphics g) 1789 { 1790 paint(g); 1791 } 1792 1793 1796 public void scrollToLine(int line) 1797 { 1798 lineToMark = line; 1799 1800 int l = 1; 1801 int pos = 0; 1802 while (l <= line && pos != -1) 1803 { 1804 pos = text.indexOf('\n', pos + 1); 1805 l ++; 1806 } 1807 setCaretPosition(pos); 1808 requestFocus(); 1809 positionVisible(); 1811 } 1812 1813 1817 public void testOposing() 1818 { 1819 if (getCaretPosition() > -1 && getCaretPosition() - 1 < text.length()) 1821 { 1822 if (getCaretPosition() > 0) 1823 { 1824 char c = text.charAt(getCaretPosition() - 1); 1825 if (c == '}') { 1826 testOpening('{','}'); 1827 } else if (c == '{') { 1828 testClosing('{','}'); 1829 } else if (c == ')') { 1830 testOpening('(',')'); 1831 } else if (c == '(') { 1832 testClosing('(',')'); 1833 } else if (c == ']') { 1834 testOpening('[',']'); 1835 } else if (c == '[') { 1836 testClosing('[',']'); 1837 } else { 1838 unmarkOposing(); 1839 } 1840 } else { 1841 repaint(); 1842 } 1843 } 1844 } 1845 1846 public void testClosing(char opening, char closing) { 1847 if (text.charAt(getCaretPosition() - 1 ) == opening) 1848 { 1849 int oldOpenPos = openPos; 1850 int oldClosePos = closePos; 1851 1852 openPos = getCaretPosition() - 1; 1853 1854 int count = 1; 1855 int pos = getCaretPosition() - 1; 1856 1857 while (pos < text.length() - 1 && count > 0) { 1858 pos ++; 1859 if (text.charAt(pos) == opening) 1860 count ++; 1861 else if (text.charAt(pos) == closing) 1862 count --; 1863 } 1864 1865 if (count > 0) { 1866 closePos = -1; 1867 openPos = -1; 1868 } else { 1869 closePos = pos; 1870 } 1871 1872 repaintCharAt(oldOpenPos); 1873 repaintCharAt(oldClosePos); 1874 repaintCharAt(openPos); 1875 repaintCharAt(closePos); 1876 repaintCharAt(caretPosition); 1877 } 1878 } 1879 1880 public void testOpening(char opening, char closing) { 1881 if (text.charAt(getCaretPosition() - 1) == closing) 1882 { 1883 int oldOpenPos = openPos; 1884 int oldClosePos = closePos; 1885 1886 openPos = getCaretPosition() - 1; 1887 1888 int count = 0; 1889 int pos = getCaretPosition() - 1; 1890 1891 if (getCaretPosition() > 0) { 1892 do { 1893 if (text.charAt(pos) == closing) 1894 count ++; 1895 else if (text.charAt(pos) == opening) 1896 count --; 1897 1898 if (count != 0) 1899 pos --; 1900 } while (pos > -1 && count > 0); 1901 } 1902 1903 closePos = pos; 1904 1905 if (closePos == -1) 1906 openPos = -1; 1907 1908 repaintCharAt(oldOpenPos); 1909 repaintCharAt(oldClosePos); 1910 repaintCharAt(openPos); 1911 repaintCharAt(closePos); 1912 repaintCharAt(caretPosition); 1913 } 1914 } 1915 1916 1919 public void unmarkOposing() 1920 { 1921 repaintCharAt(openPos); 1922 repaintCharAt(closePos); 1923 openPos = -1; 1924 closePos = -1; 1925 } 1926 1927 1930 public void positionVisible() 1931 { 1932 positionVisible(caretPosition); 1933 } 1934 1935 1938 public void selectionVisible() 1939 { 1940 positionVisible(selectionStart); 1941 } 1942 1943 1947 public void positionVisible(int position) 1948 { 1949 Object parent = getParent(); 1951 if (parent instanceof JViewport ) 1952 { 1953 Rectangle rect = getVisibleRect(); 1954 Rectangle car = getCaretPos(position); 1955 1956 try 1957 { 1958 JScrollPane scrollPane = (JScrollPane )((JViewport )parent).getParent(); 1959 JScrollBar hs = scrollPane.getHorizontalScrollBar(); 1960 JScrollBar vs = scrollPane.getVerticalScrollBar(); 1961 1962 int newX = hs.getValue(); 1963 int newY = vs.getValue(); 1964 1965 if (rect.x + rect.width - getMarginLeft() <= car.x) 1966 newX = car.x + 75 - rect.width; 1967 else if (rect.x > car.x) 1968 newX = car.x - 10; 1969 1970 if (rect.y + rect.height <= car.y + car.height) 1971 newY = car.y + 20 + car.height - rect.height; 1972 else if (rect.y >= car.y) 1973 newY = car.y - 20; 1974 1975 if (newX != hs.getValue()) { 1976 hs.setValue(newX); 1977 } 1978 if (newY != vs.getValue()) { 1979 vs.setValue(newY); 1980 } 1981 } 1982 catch(Exception e) 1983 { 1984 logger.error("positionVisible "+position, e); 1985 } 1986 } 1987 } 1988 1989 1994 public Rectangle getCaretPos(int position) 1995 { 1996 Rectangle ret = new Rectangle (0, 0, 0 ,0); 1997 1998 if (metrics != null) 1999 { 2000 int lineStart = 0; 2001 int posY = lineHeight; 2002 int i = 0; 2003 for(; i < text.length() && i < position; i ++) 2004 { 2005 if (text.charAt(i) == '\n') 2006 { 2007 lineStart = i + 1; 2008 posY += lineHeight; 2009 } 2010 } 2011 2012 ret.x = metrics.stringWidth(text.substring(lineStart, i)); 2013 ret.y = posY - lineHeight; 2014 ret.height = lineHeight; 2015 ret.width = getCharWidth('m'); 2016 } 2017 2018 return ret; 2019 } 2020 2021 2025 public void setFont(Font font) 2026 { 2027 super.setFont(font); 2028 repaint(); 2029 } 2030 2031 int OFFSET = 35; 2032 protected int getMarginLeft() { 2033 return conf.getShowLineNumbers()?OFFSET:0; 2034 } 2035 2036 2042 public int getCharPos(int mousePosX, int mousePosY) 2043 { 2044 if (metrics != null) 2045 { 2046 Rectangle rect = getVisibleRect(); 2047 2048 int pos = 0; 2049 boolean done = false; 2050 2051 String word = ""; 2052 2053 int posXStart = getMarginLeft(); 2054 int posX = posXStart; 2055 int posY = lineHeight; 2056 2057 while (posY + lineHeight < rect.y) 2058 { 2059 posY += lineHeight; 2060 if (pos + 1 < text.length()) 2061 { 2062 pos = text.indexOf('\n', pos); 2063 pos ++; 2064 } 2065 else 2066 { 2067 break; 2068 } 2069 } 2070 2071 if (mousePosY < posY - lineHeight) 2072 { 2073 return -1; 2074 } 2075 2076 while (pos < text.length()) 2077 { 2078 if (text.charAt(pos) == '\n') 2079 { 2080 if (mousePosX > posX && 2081 mousePosY < posY && 2082 mousePosY >= posY - lineHeight) 2083 { 2084 return pos; 2085 } 2086 else if (mousePosX <= posXStart && 2087 mousePosY < posY && 2088 mousePosY >= posY - lineHeight) 2089 { 2090 if (pos + 1 < text.length()) 2091 { 2092 return pos; 2093 } 2094 } 2095 posY += lineHeight; 2096 posX = posXStart; 2097 2098 } 2099 else if (posX < mousePosX && 2100 posX + (getCharWidth(text.charAt(pos)) / 2) >= mousePosX && 2101 mousePosY < posY && 2102 mousePosY >= posY - lineHeight + 2) 2103 { 2104 return pos; 2105 } 2106 else if (posX < mousePosX && 2107 posX + getCharWidth(text.charAt(pos)) >= mousePosX && 2108 mousePosY < posY && 2109 mousePosY >= posY - lineHeight) 2110 { 2111 if (pos + 1 < text.length()) 2112 { 2113 return pos + 1; 2114 } 2115 posX += getCharWidth(text.charAt(pos)); 2116 } 2117 else if (mousePosX <= posXStart && 2118 mousePosY < posY && 2119 mousePosY >= posY - lineHeight) 2120 { 2121 if (pos + 1 < text.length()) 2122 { 2123 return pos; 2124 } 2125 posX += getCharWidth(text.charAt(pos)); 2126 } 2127 else 2128 { 2129 posX += getCharWidth(text.charAt(pos)); 2130 } 2131 pos ++; 2132 } 2133 } 2134 2135 return text.length(); 2136 } 2137 2138 2143 public boolean isDivider(char c) 2144 { 2145 for(int i=0; i<separators.length; i++) { 2146 if (c == separators[i]) 2147 return true; 2148 } 2149 return false; 2150 } 2151 2152 Set keywords = new HashSet (); 2153 2157 public void addKeywords(String [] addedKeywords) { 2158 for(int i=0; i<addedKeywords.length; i++) { 2159 keywords.add(addedKeywords[i]); 2160 } 2161 } 2162 2163 2167 public void addKeywords(Set addedKeywords) { 2168 keywords.addAll(addedKeywords); 2169 } 2170 2171 public void clearKeywords() { 2172 keywords.clear(); 2173 } 2174 2175 2178 protected boolean isKeyword(String word) { 2179 return keywords.contains(word); 2180 } 2181 2182 Set modifiers = new HashSet (); 2183 2187 public void addModifiers(String [] addedModifiers) { 2188 for(int i=0; i<addedModifiers.length; i++) { 2189 modifiers.add(addedModifiers[i]); 2190 } 2191 } 2192 2195 public boolean isModifier(String word) { 2196 return modifiers.contains(word); 2197 } 2198 2199 Set types = new HashSet (); 2200 public void addTypes(String [] addedTypes) { 2201 for(int i=0; i<addedTypes.length; i++) { 2202 types.add(addedTypes[i]); 2203 } 2204 } 2205 2208 public boolean isType(String word) { 2209 if (types.contains(word)) 2210 return true; 2211 int index = word.lastIndexOf('.'); 2212 if (index!=-1) { 2213 word = word.substring(index+1); 2214 } 2215 return word.length()>1 && 2216 Character.isUpperCase(word.charAt(0)) && 2217 Character.isLowerCase(word.charAt(1)); 2218 } 2219 2220 public void setCaretPosition(int caretPosition) { 2221 repaintCharAt(this.caretPosition); 2222 if (caretPosition<0) 2223 caretPosition = 0; 2224 else if (caretPosition>text.length()) 2225 caretPosition = text.length(); 2226 this.caretPosition = caretPosition; 2227 repaintCharAt(caretPosition); 2228 fireCaretUpdate(); 2229 } 2230 2231 protected void repaintCharAt(int pos) { 2232 if (pos!=-1) { 2233 Rectangle rect = getCaretPos(pos); 2234 logger.debug("repaintCharAt "+pos+" -> "+rect); 2235 repaint(rect); 2236 } 2237 } 2238 2239 protected void repaintChars(int start, int end) { 2240 if (start<end) 2241 for (int p=start; p<=end; p++) 2242 repaintCharAt(p); 2243 else 2244 for (int p=end; p<=start; p++) 2245 repaintCharAt(p); 2246 } 2247 2248 2252 public int getCaretPosition() 2253 { 2254 return caretPosition; 2255 } 2256 2257 2261 public int getSelectionStart() 2262 { 2263 return selectionStart; 2264 } 2265 2266 2270 public int getSelectionEnd() 2271 { 2272 return selectionEnd; 2273 } 2274 2275 2278 public void mousePressed(MouseEvent e) 2279 { 2280 requestFocus(); 2281 int tmp = getCharPos(e.getX(), e.getY()); 2282 mousePressPos = tmp; 2283 if (tmp != -1) 2284 { 2285 isSelectionCompletion = false; 2286 if ((e.getModifiers() & MouseEvent.SHIFT_MASK) > 0) 2287 { 2288 if (caretPosition == selectionStart && tmp <= selectionEnd) { 2289 setCaretPosition(tmp); 2290 selectionStart = caretPosition; 2291 } else if (caretPosition == selectionStart) { 2292 selectionStart = selectionEnd; 2293 setCaretPosition(tmp); 2294 selectionEnd = caretPosition; 2295 } else if (caretPosition == selectionEnd && tmp >= selectionStart) { 2296 setCaretPosition(tmp); 2297 selectionEnd = caretPosition; 2298 } else { 2299 selectionEnd = selectionStart; 2300 setCaretPosition(tmp); 2301 selectionStart = caretPosition; 2302 } 2303 } 2304 else 2305 { 2306 setCaretPosition(tmp); 2307 if (e.getClickCount()==1) { 2308 selectionEnd = caretPosition; 2309 selectionStart = caretPosition; 2310 } 2311 } 2312 2313 repaint(); 2314 positionVisible(); 2315 } 2316 } 2317 2318 2321 public void mouseMoved(MouseEvent e) 2322 { 2323 } 2324 2325 2328 public void mouseDragged(MouseEvent e) 2329 { 2330 int tmp = getCharPos(e.getX(), e.getY()); 2331 if (mousePressPos != -1) { 2332 if (mousePressPos <= tmp) { 2333 selectionStart = mousePressPos; 2334 selectionEnd = tmp; 2335 } else { 2336 selectionEnd = mousePressPos; 2337 selectionStart = tmp; 2338 } 2339 setCaretPosition(tmp); 2340 repaint(); 2341 positionVisible(); 2342 } else { 2343 repaint(); 2344 } 2345 } 2346 2347 2350 public void mouseReleased(MouseEvent e) 2351 { 2352 mousePressPos = -1; 2353 testOposing(); 2354 } 2355 2356 2359 public void mouseClicked(MouseEvent e) 2360 { 2361 if (e.getClickCount()==2) { 2362 selectWord(caretPosition); 2363 } 2364 } 2365 2366 2369 public void mouseEntered(MouseEvent e) 2370 { 2371 } 2372 2373 2376 public void mouseExited(MouseEvent e) 2377 { 2378 } 2379 2380 protected int minDisplayedLines = 4; 2381 2384 public int getMinDisplayedLines() { 2385 return minDisplayedLines; 2386 } 2387 public void setMinDisplayedLines(int n) { 2388 this.minDisplayedLines = n; 2389 } 2390 2391 public Dimension getPreferredScrollableViewportSize() 2392 { 2393 int pos = 0; 2394 int lineStart = 0; 2395 int width = 30; 2396 int height; 2397 int lines = 1; 2398 2399 while (pos < text.length()) 2400 { 2401 if (text.charAt(pos)=='\n' || pos==(text.length()-1)) { 2402 int lineWidth = 2403 metrics.stringWidth( 2404 Strings.replace(text.substring(lineStart,pos), 2405 "\t", 2406 Strings.newString(' ',conf.getTabWidth()))) 2407 + metrics.charWidth('m'); 2408 if (lineWidth>width) 2409 width = lineWidth; 2410 lineStart = pos+1; 2411 lines++; 2412 } 2413 pos++; 2414 } 2415 if (lines<minDisplayedLines) 2416 lines = minDisplayedLines; 2417 height = lines * metrics.getHeight(); 2418 return new Dimension (width,height); 2419 } 2420 2421 public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) 2422 { 2423 return metrics.getHeight(); 2424 } 2425 2426 2429 public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) 2430 { 2431 switch(orientation) 2432 { 2433 case SwingConstants.VERTICAL: 2434 return visibleRect.height; 2435 case SwingConstants.HORIZONTAL: 2436 return visibleRect.width; 2437 default: 2438 throw new IllegalArgumentException ("Invalid orientation: " + orientation); 2439 } 2440 } 2441 2442 public boolean getScrollableTracksViewportWidth() 2443 { 2444 Object parent = getParent(); 2446 return (parent instanceof JViewport ) && 2447 (((JViewport )parent).getWidth() > getPreferredSize().width); 2448 } 2449 public boolean getScrollableTracksViewportHeight() 2450 { 2451 Object parent = getParent(); 2453 return (parent instanceof JViewport ) && 2454 (((JViewport )parent).getHeight() > getPreferredSize().height); 2455 } 2456 2457 2458 2459 2462 public void lostOwnership(Clipboard cb, Transferable tr) 2463 { 2464 } 2465 2466 2469 public void focusLost(FocusEvent e) 2470 { 2471 repaintCharAt(caretPosition); 2472 } 2473 2474 2477 public void focusGained(FocusEvent e) 2478 { 2479 repaintCharAt(caretPosition); 2480 } 2481 2482 2486 public void readFromFile(File f) 2487 { 2488 try 2489 { 2490 StringBuffer tmp = new StringBuffer (); 2491 if (f.exists()) 2492 { 2493 BufferedReader in = 2494 new BufferedReader ( 2495 new InputStreamReader ( 2496 new BufferedInputStream ( 2497 new FileInputStream (f)))); 2498 2499 String read = in.readLine(); 2500 boolean first = true; 2501 2502 while (read != null) 2503 { 2504 if (!first) 2505 { 2506 tmp.append("\n" + read); 2507 } 2508 else 2509 { 2510 first = false; 2511 tmp.append(read); 2512 } 2513 read = in.readLine(); 2514 } 2515 in.close(); 2516 text = tmp.toString(); 2517 } 2518 } 2519 catch(IOException e) 2520 { 2521 System.out.println("Error: " + e); 2522 } 2523 changed = false; 2524 } 2525 2526 2530 public void saveToFile(File f) 2531 { 2532 try 2533 { 2534 PrintWriter out = new PrintWriter (new FileWriter (f)); 2535 out.print(text); 2536 out.close(); 2537 } 2538 catch(IOException e) 2539 { 2540 System.out.println("Error: " + e); 2541 } 2542 changed = false; 2543 } 2544 2545 2548 static class TextAction 2549 { 2550 2553 public final static int REMOVE = 0; 2554 2557 public final static int INSERT = 1; 2558 2559 int action; 2560 int position; 2561 int length; 2562 String string; 2563 2564 2571 TextAction(int a, int p, int l, String s) 2572 { 2573 action = a; 2574 position = p; 2575 length = l; 2576 string = s; 2577 } 2578 } 2579 2580 static class MutableCaretEvent extends CaretEvent { 2581 public MutableCaretEvent(Object source, int caretPosition) { 2582 super(source); 2583 this.caretPosition = caretPosition; 2584 } 2585 int caretPosition; 2586 public int getDot() { 2587 return caretPosition; 2588 } 2589 public int getMark() { 2590 return -1; 2591 } 2592 } 2593} 2594 | Popular Tags |