1 package com.opensymphony.workflow.designer.swing; 2 3 import java.awt.*; 4 import java.io.IOException ; 5 import java.io.Reader ; 6 import java.util.*; 7 import javax.swing.*; 8 import javax.swing.text.*; 9 10 import com.Ostermiller.Syntax.Lexer.JavaLexer; 11 import com.Ostermiller.Syntax.Lexer.Lexer; 12 import com.Ostermiller.Syntax.Lexer.Token; 13 14 19 public class JavaTextPane extends JTextPane 20 { 21 25 private static StyleContext styleContext = new StyleContext(); 26 static 27 { 28 initStyles(); 29 } 30 34 protected HighLightedDocument document; 35 40 protected DocumentReader documentReader; 41 45 protected Lexer syntaxLexer; 46 47 protected Colorer colorer; 48 53 private Object doclock = new Object (); 54 55 public JavaTextPane() 56 { 57 super(); 58 document = new HighLightedDocument(styleContext); 59 setDocument(document); 60 setCaretPosition(0); 61 setMargin(new Insets(5, 5, 5, 5)); 62 colorer = new Colorer(); 63 colorer.start(); 64 documentReader = new DocumentReader(this.document); 66 67 syntaxLexer = new JavaLexer(documentReader); 68 } 69 70 75 private class Colorer extends Thread 76 { 77 78 85 private TreeSet iniPositions = new TreeSet(new DocPositionComparator()); 86 87 94 private HashSet newPositions = new HashSet(); 95 96 100 private class RecolorEvent 101 { 102 public int position; 103 public int adjustment; 104 105 public RecolorEvent(int position, int adjustment) 106 { 107 this.position = position; 108 this.adjustment = adjustment; 109 } 110 } 111 112 113 private volatile Vector v = new Vector(); 114 115 119 private volatile int change = 0; 120 121 122 private volatile int lastPosition = -1; 123 124 private volatile boolean asleep = false; 125 126 131 private Object lock = new Object (); 132 133 138 public void color(int position, int adjustment) 139 { 140 if(position < lastPosition) 144 { 145 if(lastPosition < position - adjustment) 146 { 147 change -= lastPosition - position; 148 } 149 else 150 { 151 change += adjustment; 152 } 153 } 154 synchronized(lock) 155 { 156 v.add(new RecolorEvent(position, adjustment)); 157 if(asleep) 158 { 159 this.interrupt(); 160 } 161 } 162 } 163 164 169 public void run() 170 { 171 int position = -1; 172 int adjustment = 0; 173 boolean tryAgain = false; 177 for(; ;) 178 { synchronized(lock) 180 { 181 if(v.size() > 0) 182 { 183 RecolorEvent re = (RecolorEvent)(v.elementAt(0)); 184 v.removeElementAt(0); 185 position = re.position; 186 adjustment = re.adjustment; 187 } 188 else 189 { 190 tryAgain = false; 191 position = -1; 192 adjustment = 0; 193 } 194 } 195 if(position != -1) 196 { 197 SortedSet workingSet; 198 Iterator workingIt; 199 DocPosition startRequest = new DocPosition(position); 200 DocPosition endRequest = new DocPosition(position + ((adjustment >= 0) ? adjustment : -adjustment)); 201 DocPosition dp; 202 DocPosition dpStart = null; 203 DocPosition dpEnd = null; 204 205 try 208 { 209 workingSet = iniPositions.headSet(startRequest); 211 dpStart = ((DocPosition)workingSet.last()); 213 } 214 catch(NoSuchElementException x) 215 { 216 dpStart = new DocPosition(0); 219 } 220 221 if(adjustment < 0) 223 { 224 workingSet = iniPositions.subSet(startRequest, endRequest); 225 workingIt = workingSet.iterator(); 226 while(workingIt.hasNext()) 227 { 228 workingIt.next(); 229 workingIt.remove(); 230 } 231 } 232 233 workingSet = iniPositions.tailSet(startRequest); 235 workingIt = workingSet.iterator(); 236 while(workingIt.hasNext()) 237 { 238 ((DocPosition)workingIt.next()).adjustPosition(adjustment); 239 } 240 241 workingSet = iniPositions.tailSet(dpStart); 243 workingIt = workingSet.iterator(); 244 dp = null; 245 if(workingIt.hasNext()) 246 { 247 dp = (DocPosition)workingIt.next(); 248 } 249 try 250 { 251 Token t; 252 boolean done = false; 253 dpEnd = dpStart; 254 synchronized(doclock) 255 { 256 syntaxLexer.reset(documentReader, 0, dpStart.getPosition(), 0); 264 documentReader.seek(dpStart.getPosition()); 267 t = syntaxLexer.getNextToken(); 272 } 273 newPositions.add(dpStart); 274 while(!done && t != null) 275 { 276 synchronized(doclock) 280 { 281 if(t.getCharEnd() <= document.getLength()) 282 { 283 Style style = getStyle(t.getDescription()); 284 document.setCharacterAttributes(t.getCharBegin() + change, t.getCharEnd() - t.getCharBegin(), style, true); 285 dpEnd = new DocPosition(t.getCharEnd()); 287 } 288 lastPosition = (t.getCharEnd() + change); 289 } 290 if(t.getState() == Token.INITIAL_STATE) 298 { 299 while(dp != null && dp.getPosition() <= t.getCharEnd()) 303 { 304 if(dp.getPosition() == t.getCharEnd() && dp.getPosition() >= endRequest.getPosition()) 305 { 306 done = true; 308 dp = null; 309 } 310 else if(workingIt.hasNext()) 311 { 312 dp = (DocPosition)workingIt.next(); 314 } 315 else 316 { 317 dp = null; 321 } 322 } 323 newPositions.add(dpEnd); 326 } 327 synchronized(doclock) 328 { 329 t = syntaxLexer.getNextToken(); 330 } 331 } 332 333 workingIt = iniPositions.subSet(dpStart, dpEnd).iterator(); 337 while(workingIt.hasNext()) 338 { 339 workingIt.next(); 340 workingIt.remove(); 341 } 342 343 workingIt = iniPositions.tailSet(new DocPosition(document.getLength())).iterator(); 345 while(workingIt.hasNext()) 346 { 347 workingIt.next(); 348 workingIt.remove(); 349 } 350 351 iniPositions.addAll(newPositions); 353 newPositions.clear(); 354 355 361 } 362 catch(IOException x) 363 { 364 } 365 synchronized(doclock) 366 { 367 lastPosition = -1; 368 change = 0; 369 } 370 tryAgain = true; 373 } 374 asleep = true; 375 if(!tryAgain) 376 { 377 try 378 { 379 sleep(0xffffff); 380 } 381 catch(InterruptedException x) 382 { 383 } 384 385 } 386 asleep = false; 387 } 388 } 389 } 390 391 394 public void colorAll() 395 { 396 color(0, document.getLength()); 397 } 398 399 409 public void color(int position, int adjustment) 410 { 411 colorer.color(position, adjustment); 412 } 413 414 418 private class HighLightedDocument extends DefaultStyledDocument 419 { 420 public HighLightedDocument(StyleContext styles) 421 { 422 super(styles); 423 } 424 425 public void insertString(int offs, String str, AttributeSet a) throws BadLocationException 426 { 427 synchronized(doclock) 428 { 429 super.insertString(offs, str, a); 430 color(offs, str.length()); 431 documentReader.update(offs, str.length()); 432 } 433 } 434 435 public void remove(int offs, int len) throws BadLocationException 436 { 437 synchronized(doclock) 438 { 439 super.remove(offs, len); 440 color(offs, -len); 441 documentReader.update(offs, -len); 442 } 443 } 444 } 445 446 450 class DocPosition 451 { 452 453 454 private int position; 455 456 461 int getPosition() 462 { 463 return position; 464 } 465 466 471 public DocPosition(int position) 472 { 473 this.position = position; 474 } 475 476 484 public DocPosition adjustPosition(int adjustment) 485 { 486 position += adjustment; 487 return this; 488 } 489 490 495 public boolean equals(Object obj) 496 { 497 if(obj instanceof DocPosition) 498 { 499 DocPosition d = (DocPosition)(obj); 500 if(this.position == d.position) 501 { 502 return true; 503 } 504 else 505 { 506 return false; 507 } 508 } 509 else 510 { 511 return false; 512 } 513 } 514 515 520 public String toString() 521 { 522 return "" + position; 523 } 524 } 525 526 530 class DocPositionComparator implements Comparator 531 { 532 539 public boolean equals(Object obj) 540 { 541 if(obj instanceof DocPositionComparator) 542 { 543 return true; 544 } 545 else 546 { 547 return false; 548 } 549 } 550 551 558 public int compare(Object o1, Object o2) 559 { 560 if(o1 instanceof DocPosition && o2 instanceof DocPosition) 561 { 562 DocPosition d1 = (DocPosition)(o1); 563 DocPosition d2 = (DocPosition)(o2); 564 return (d1.getPosition() - d2.getPosition()); 565 } 566 else if(o1 instanceof DocPosition) 567 { 568 return -1; 569 } 570 else if(o2 instanceof DocPosition) 571 { 572 return 1; 573 } 574 else if(o1.hashCode() < o2.hashCode()) 575 { 576 return -1; 577 } 578 else if(o2.hashCode() > o1.hashCode()) 579 { 580 return 1; 581 } 582 else 583 { 584 return 0; 585 } 586 } 587 } 588 589 599 class DocumentReader extends Reader 600 { 601 602 609 public void update(int position, int adjustment) 610 { 611 if(position < this.position) 612 { 613 if(this.position < position - adjustment) 614 { 615 this.position = position; 616 } 617 else 618 { 619 this.position += adjustment; 620 } 621 } 622 } 623 624 628 private long position = 0; 629 630 631 private long mark = -1; 632 633 634 private AbstractDocument document; 635 636 641 public DocumentReader(AbstractDocument document) 642 { 643 this.document = document; 644 } 645 646 650 public void close() 651 { 652 } 653 654 659 public void mark(int readAheadLimit) 660 { 661 mark = position; 662 } 663 664 669 public boolean markSupported() 670 { 671 return true; 672 } 673 674 679 public int read() 680 { 681 if(position < document.getLength()) 682 { 683 try 684 { 685 char c = document.getText((int)position, 1).charAt(0); 686 position++; 687 return c; 688 } 689 catch(BadLocationException x) 690 { 691 return -1; 692 } 693 } 694 else 695 { 696 return -1; 697 } 698 } 699 700 707 public int read(char[] cbuf) 708 { 709 return read(cbuf, 0, cbuf.length); 710 } 711 712 721 public int read(char[] cbuf, int off, int len) 722 { 723 if(position < document.getLength()) 724 { 725 int length = len; 726 if(position + length >= document.getLength()) 727 { 728 length = document.getLength() - (int)position; 729 } 730 if(off + length >= cbuf.length) 731 { 732 length = cbuf.length - off; 733 } 734 try 735 { 736 String s = document.getText((int)position, length); 737 position += length; 738 for(int i = 0; i < length; i++) 739 { 740 cbuf[off + i] = s.charAt(i); 741 } 742 return length; 743 } 744 catch(BadLocationException x) 745 { 746 return -1; 747 } 748 } 749 else 750 { 751 return -1; 752 } 753 } 754 755 758 public boolean ready() 759 { 760 return true; 761 } 762 763 766 public void reset() 767 { 768 if(mark == -1) 769 { 770 position = 0; 771 } 772 else 773 { 774 position = mark; 775 } 776 mark = -1; 777 } 778 779 787 public long skip(long n) 788 { 789 if(position + n <= document.getLength()) 790 { 791 position += n; 792 return n; 793 } 794 else 795 { 796 long oldPos = position; 797 position = document.getLength(); 798 return (document.getLength() - oldPos); 799 } 800 } 801 802 807 public void seek(long n) 808 { 809 if(n <= document.getLength()) 810 { 811 position = n; 812 } 813 else 814 { 815 position = document.getLength(); 816 } 817 } 818 } 819 820 private static void initStyles() 821 { 822 Style style; 823 style = styleContext.addStyle("body", null); 824 StyleConstants.setFontFamily(style, "Monospaced"); 825 StyleConstants.setFontSize(style, 12); 826 StyleConstants.setBackground(style, Color.white); 827 StyleConstants.setForeground(style, Color.black); 828 StyleConstants.setBold(style, false); 829 StyleConstants.setItalic(style, false); 830 831 style = styleContext.addStyle("tag", null); 832 StyleConstants.setFontFamily(style, "Monospaced"); 833 StyleConstants.setFontSize(style, 12); 834 StyleConstants.setBackground(style, Color.white); 835 StyleConstants.setForeground(style, Color.blue); 836 StyleConstants.setBold(style, true); 837 StyleConstants.setItalic(style, false); 838 839 style = styleContext.addStyle("endtag", null); 840 StyleConstants.setFontFamily(style, "Monospaced"); 841 StyleConstants.setFontSize(style, 12); 842 StyleConstants.setBackground(style, Color.white); 843 StyleConstants.setForeground(style, Color.blue); 844 StyleConstants.setBold(style, false); 845 StyleConstants.setItalic(style, false); 846 847 style = styleContext.addStyle("reference", null); 848 StyleConstants.setFontFamily(style, "Monospaced"); 849 StyleConstants.setFontSize(style, 12); 850 StyleConstants.setBackground(style, Color.white); 851 StyleConstants.setForeground(style, Color.black); 852 StyleConstants.setBold(style, false); 853 StyleConstants.setItalic(style, false); 854 855 style = styleContext.addStyle("name", null); 856 StyleConstants.setFontFamily(style, "Monospaced"); 857 StyleConstants.setFontSize(style, 12); 858 StyleConstants.setBackground(style, Color.white); 859 StyleConstants.setForeground(style, new Color(0xB03060)); 860 StyleConstants.setBold(style, true); 861 StyleConstants.setItalic(style, false); 862 863 style = styleContext.addStyle("value", null); 864 StyleConstants.setFontFamily(style, "Monospaced"); 865 StyleConstants.setFontSize(style, 12); 866 StyleConstants.setBackground(style, Color.white); 867 StyleConstants.setForeground(style, new Color(0xB03060)); 868 StyleConstants.setBold(style, false); 869 StyleConstants.setItalic(style, true); 870 871 style = styleContext.addStyle("tag", null); 872 StyleConstants.setFontFamily(style, "Monospaced"); 873 StyleConstants.setFontSize(style, 12); 874 StyleConstants.setBackground(style, Color.white); 875 StyleConstants.setForeground(style, Color.black); 876 StyleConstants.setBold(style, true); 877 StyleConstants.setItalic(style, false); 878 879 style = styleContext.addStyle("reservedWord", null); 880 StyleConstants.setFontFamily(style, "Monospaced"); 881 StyleConstants.setFontSize(style, 12); 882 StyleConstants.setBackground(style, Color.white); 883 StyleConstants.setForeground(style, Color.blue); 884 StyleConstants.setBold(style, false); 885 StyleConstants.setItalic(style, false); 886 887 style = styleContext.addStyle("identifier", null); 888 StyleConstants.setFontFamily(style, "Monospaced"); 889 StyleConstants.setFontSize(style, 12); 890 StyleConstants.setBackground(style, Color.white); 891 StyleConstants.setForeground(style, Color.black); 892 StyleConstants.setBold(style, false); 893 StyleConstants.setItalic(style, false); 894 895 style = styleContext.addStyle("literal", null); 896 StyleConstants.setFontFamily(style, "Monospaced"); 897 StyleConstants.setFontSize(style, 12); 898 StyleConstants.setBackground(style, Color.white); 899 StyleConstants.setForeground(style, new Color(0xB03060)); 900 StyleConstants.setBold(style, false); 901 StyleConstants.setItalic(style, false); 902 903 style = styleContext.addStyle("separator", null); 904 StyleConstants.setFontFamily(style, "Monospaced"); 905 StyleConstants.setFontSize(style, 12); 906 StyleConstants.setBackground(style, Color.white); 907 StyleConstants.setForeground(style, new Color(0x000080)); 908 StyleConstants.setBold(style, false); 909 StyleConstants.setItalic(style, false); 910 911 style = styleContext.addStyle("operator", null); 912 StyleConstants.setFontFamily(style, "Monospaced"); 913 StyleConstants.setFontSize(style, 12); 914 StyleConstants.setBackground(style, Color.white); 915 StyleConstants.setForeground(style, Color.black); 916 StyleConstants.setBold(style, true); 917 StyleConstants.setItalic(style, false); 918 919 style = styleContext.addStyle("comment", null); 920 StyleConstants.setFontFamily(style, "Monospaced"); 921 StyleConstants.setFontSize(style, 12); 922 StyleConstants.setBackground(style, Color.white); 923 StyleConstants.setForeground(style, Color.green.darker()); 924 StyleConstants.setBold(style, false); 925 StyleConstants.setItalic(style, false); 926 927 style = styleContext.addStyle("preprocessor", null); 928 StyleConstants.setFontFamily(style, "Monospaced"); 929 StyleConstants.setFontSize(style, 12); 930 StyleConstants.setBackground(style, Color.white); 931 StyleConstants.setForeground(style, new Color(0xA020F0).darker()); 932 StyleConstants.setBold(style, false); 933 StyleConstants.setItalic(style, false); 934 935 style = styleContext.addStyle("whitespace", null); 936 StyleConstants.setFontFamily(style, "Monospaced"); 937 StyleConstants.setFontSize(style, 12); 938 StyleConstants.setBackground(style, Color.white); 939 StyleConstants.setForeground(style, Color.black); 940 StyleConstants.setBold(style, false); 941 StyleConstants.setItalic(style, false); 942 943 style = styleContext.addStyle("error", null); 944 StyleConstants.setFontFamily(style, "Monospaced"); 945 StyleConstants.setFontSize(style, 12); 946 StyleConstants.setBackground(style, Color.white); 947 StyleConstants.setForeground(style, Color.red); 948 StyleConstants.setBold(style, false); 949 StyleConstants.setItalic(style, false); 950 951 style = styleContext.addStyle("unknown", null); 952 StyleConstants.setFontFamily(style, "Monospaced"); 953 StyleConstants.setFontSize(style, 12); 954 StyleConstants.setBackground(style, Color.white); 955 StyleConstants.setForeground(style, Color.orange); 956 StyleConstants.setBold(style, false); 957 StyleConstants.setItalic(style, false); 958 } 959 } 960 | Popular Tags |