1 package org.jedit.syntax; 2 3 11 12 import javax.swing.ToolTipManager ; 13 import javax.swing.text.*; 14 import javax.swing.JComponent ; 15 import java.awt.event.MouseEvent ; 16 import java.awt.*; 17 18 24 public class TextAreaPainter extends JComponent implements TabExpander 25 { 26 30 public TextAreaPainter(JEditTextArea textArea, TextAreaDefaults defaults) 31 { 32 this.textArea = textArea; 33 34 setAutoscrolls(true); 35 setDoubleBuffered(true); 36 setOpaque(true); 37 38 ToolTipManager.sharedInstance().registerComponent(this); 39 40 currentLine = new Segment(); 41 currentLineIndex = -1; 42 43 setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); 44 45 setFont(new Font("Monospaced",Font.PLAIN,14)); 46 setForeground(Color.black); 47 setBackground(Color.white); 48 49 blockCaret = defaults.blockCaret; 50 styles = defaults.styles; 51 cols = defaults.cols; 52 rows = defaults.rows; 53 caretColor = defaults.caretColor; 54 selectionColor = defaults.selectionColor; 55 lineHighlightColor = defaults.lineHighlightColor; 56 lineHighlight = defaults.lineHighlight; 57 bracketHighlightColor = defaults.bracketHighlightColor; 58 bracketHighlight = defaults.bracketHighlight; 59 paintInvalid = defaults.paintInvalid; 60 eolMarkerColor = defaults.eolMarkerColor; 61 eolMarkers = defaults.eolMarkers; 62 } 63 64 68 public final boolean isManagingFocus() 69 { 70 return false; 71 } 72 73 78 public final SyntaxStyle[] getStyles() 79 { 80 return styles; 81 } 82 83 89 public final void setStyles(SyntaxStyle[] styles) 90 { 91 this.styles = styles; 92 repaint(); 93 } 94 95 98 public final Color getCaretColor() 99 { 100 return caretColor; 101 } 102 103 107 public final void setCaretColor(Color caretColor) 108 { 109 this.caretColor = caretColor; 110 invalidateSelectedLines(); 111 } 112 113 116 public final Color getSelectionColor() 117 { 118 return selectionColor; 119 } 120 121 125 public final void setSelectionColor(Color selectionColor) 126 { 127 this.selectionColor = selectionColor; 128 invalidateSelectedLines(); 129 } 130 131 134 public final Color getLineHighlightColor() 135 { 136 return lineHighlightColor; 137 } 138 139 143 public final void setLineHighlightColor(Color lineHighlightColor) 144 { 145 this.lineHighlightColor = lineHighlightColor; 146 invalidateSelectedLines(); 147 } 148 149 152 public final boolean isLineHighlightEnabled() 153 { 154 return lineHighlight; 155 } 156 157 162 public final void setLineHighlightEnabled(boolean lineHighlight) 163 { 164 this.lineHighlight = lineHighlight; 165 invalidateSelectedLines(); 166 } 167 168 171 public final Color getBracketHighlightColor() 172 { 173 return bracketHighlightColor; 174 } 175 176 180 public final void setBracketHighlightColor(Color bracketHighlightColor) 181 { 182 this.bracketHighlightColor = bracketHighlightColor; 183 invalidateLine(textArea.getBracketLine()); 184 } 185 186 191 public final boolean isBracketHighlightEnabled() 192 { 193 return bracketHighlight; 194 } 195 196 203 public final void setBracketHighlightEnabled(boolean bracketHighlight) 204 { 205 this.bracketHighlight = bracketHighlight; 206 invalidateLine(textArea.getBracketLine()); 207 } 208 209 212 public final boolean isBlockCaretEnabled() 213 { 214 return blockCaret; 215 } 216 217 222 public final void setBlockCaretEnabled(boolean blockCaret) 223 { 224 this.blockCaret = blockCaret; 225 invalidateSelectedLines(); 226 } 227 228 231 public final Color getEOLMarkerColor() 232 { 233 return eolMarkerColor; 234 } 235 236 240 public final void setEOLMarkerColor(Color eolMarkerColor) 241 { 242 this.eolMarkerColor = eolMarkerColor; 243 repaint(); 244 } 245 246 249 public final boolean getEOLMarkersPainted() 250 { 251 return eolMarkers; 252 } 253 254 258 public final void setEOLMarkersPainted(boolean eolMarkers) 259 { 260 this.eolMarkers = eolMarkers; 261 repaint(); 262 } 263 264 268 public boolean getInvalidLinesPainted() 269 { 270 return paintInvalid; 271 } 272 273 277 public void setInvalidLinesPainted(boolean paintInvalid) 278 { 279 this.paintInvalid = paintInvalid; 280 } 281 282 286 public void addCustomHighlight(Highlight highlight) 287 { 288 highlight.init(textArea,highlights); 289 highlights = highlight; 290 } 291 292 295 public interface Highlight 296 { 297 302 void init(JEditTextArea textArea, Highlight next); 303 304 311 void paintHighlight(Graphics gfx, int line, int y); 312 313 320 String getToolTipText(MouseEvent evt); 321 } 322 323 327 public String getToolTipText(MouseEvent evt) 328 { 329 if(highlights != null) 330 return highlights.getToolTipText(evt); 331 else 332 return null; 333 } 334 335 338 public FontMetrics getFontMetrics() 339 { 340 return fm; 341 } 342 343 348 public void setFont(Font font) 349 { 350 super.setFont(font); 351 fm = Toolkit.getDefaultToolkit().getFontMetrics(font); 352 textArea.recalculateVisibleLines(); 353 } 354 355 359 public void paint(Graphics gfx) 360 { 361 tabSize = fm.charWidth(' ') * ((Integer )textArea 362 .getDocument().getProperty( 363 PlainDocument.tabSizeAttribute)).intValue(); 364 365 Rectangle clipRect = gfx.getClipBounds(); 366 367 gfx.setColor(getBackground()); 368 gfx.fillRect(clipRect.x,clipRect.y,clipRect.width,clipRect.height); 369 370 int height = fm.getHeight(); 373 int firstLine = textArea.getFirstLine(); 374 int firstInvalid = firstLine + clipRect.y / height; 375 int lastInvalid = firstLine + (clipRect.y + clipRect.height - 1) / height; 379 380 try 381 { 382 TokenMarker tokenMarker = textArea.getDocument() 383 .getTokenMarker(); 384 int x = textArea.getHorizontalOffset(); 385 386 for(int line = firstInvalid; line <= lastInvalid; line++) 387 { 388 paintLine(gfx,tokenMarker,line,x); 389 } 390 391 if(tokenMarker != null && tokenMarker.isNextLineRequested()) 392 { 393 int h = clipRect.y + clipRect.height; 394 repaint(0,h,getWidth(),getHeight() - h); 395 } 396 } 397 catch(Exception e) 398 { 399 System.err.println("Error repainting line" 400 + " range {" + firstInvalid + "," 401 + lastInvalid + "}:"); 402 e.printStackTrace(); 403 } 404 } 405 406 410 public final void invalidateLine(int line) 411 { 412 repaint(0,textArea.lineToY(line) + fm.getMaxDescent() + fm.getLeading(), 413 getWidth(),fm.getHeight()); 414 } 415 416 421 public final void invalidateLineRange(int firstLine, int lastLine) 422 { 423 repaint(0,textArea.lineToY(firstLine) + fm.getMaxDescent() + fm.getLeading(), 424 getWidth(),(lastLine - firstLine + 1) * fm.getHeight()); 425 } 426 427 430 public final void invalidateSelectedLines() 431 { 432 invalidateLineRange(textArea.getSelectionStartLine(), 433 textArea.getSelectionEndLine()); 434 } 435 436 443 public float nextTabStop(float x, int tabOffset) 444 { 445 int offset = textArea.getHorizontalOffset(); 446 int ntabs = ((int)x - offset) / tabSize; 447 return (ntabs + 1) * tabSize + offset; 448 } 449 450 453 public Dimension getPreferredSize() 454 { 455 Dimension dim = new Dimension(); 456 dim.width = fm.charWidth('w') * cols; 457 dim.height = fm.getHeight() * rows; 458 return dim; 459 } 460 461 462 465 public Dimension getMinimumSize() 466 { 467 return getPreferredSize(); 468 } 469 470 int currentLineIndex; 472 Token currentLineTokens; 473 Segment currentLine; 474 475 protected JEditTextArea textArea; 477 478 protected SyntaxStyle[] styles; 479 protected Color caretColor; 480 protected Color selectionColor; 481 protected Color lineHighlightColor; 482 protected Color bracketHighlightColor; 483 protected Color eolMarkerColor; 484 485 protected boolean blockCaret; 486 protected boolean lineHighlight; 487 protected boolean bracketHighlight; 488 protected boolean paintInvalid; 489 protected boolean eolMarkers; 490 protected int cols; 491 protected int rows; 492 493 protected int tabSize; 494 protected FontMetrics fm; 495 496 protected Highlight highlights; 497 498 protected void paintLine(Graphics gfx, TokenMarker tokenMarker, 499 int line, int x) 500 { 501 Font defaultFont = getFont(); 502 Color defaultColor = getForeground(); 503 504 currentLineIndex = line; 505 int y = textArea.lineToY(line); 506 507 if(line < 0 || line >= textArea.getLineCount()) 508 { 509 if(paintInvalid) 510 { 511 paintHighlight(gfx,line,y); 512 styles[Token.INVALID].setGraphicsFlags(gfx,defaultFont); 513 gfx.drawString("~",0,y + fm.getHeight()); 514 } 515 } 516 else if(tokenMarker == null) 517 { 518 paintPlainLine(gfx,line,defaultFont,defaultColor,x,y); 519 } 520 else 521 { 522 paintSyntaxLine(gfx,tokenMarker,line,defaultFont, 523 defaultColor,x,y); 524 } 525 } 526 527 protected void paintPlainLine(Graphics gfx, int line, Font defaultFont, 528 Color defaultColor, int x, int y) 529 { 530 paintHighlight(gfx,line,y); 531 textArea.getLineText(line,currentLine); 532 533 gfx.setFont(defaultFont); 534 gfx.setColor(defaultColor); 535 536 y += fm.getHeight(); 537 x = Utilities.drawTabbedText(currentLine,x,y,gfx,this,0); 538 539 if(eolMarkers) 540 { 541 gfx.setColor(eolMarkerColor); 542 gfx.drawString(".",x,y); 543 } 544 } 545 546 protected void paintSyntaxLine(Graphics gfx, TokenMarker tokenMarker, 547 int line, Font defaultFont, Color defaultColor, int x, int y) 548 { 549 textArea.getLineText(currentLineIndex,currentLine); 550 currentLineTokens = tokenMarker.markTokens(currentLine, 551 currentLineIndex); 552 553 paintHighlight(gfx,line,y); 554 555 gfx.setFont(defaultFont); 556 gfx.setColor(defaultColor); 557 y += fm.getHeight(); 558 x = SyntaxUtilities.paintSyntaxLine(currentLine, 559 currentLineTokens,styles,this,gfx,x,y); 560 561 if(eolMarkers) 562 { 563 gfx.setColor(eolMarkerColor); 564 gfx.drawString(".",x,y); 565 } 566 } 567 568 protected void paintHighlight(Graphics gfx, int line, int y) 569 { 570 if(line >= textArea.getSelectionStartLine() 571 && line <= textArea.getSelectionEndLine()) 572 paintLineHighlight(gfx,line,y); 573 574 if(highlights != null) 575 highlights.paintHighlight(gfx,line,y); 576 577 if(bracketHighlight && line == textArea.getBracketLine()) 578 paintBracketHighlight(gfx,line,y); 579 580 if(line == textArea.getCaretLine()) 581 paintCaret(gfx,line,y); 582 } 583 584 protected void paintLineHighlight(Graphics gfx, int line, int y) 585 { 586 int height = fm.getHeight(); 587 y += fm.getLeading() + fm.getMaxDescent(); 588 589 int selectionStart = textArea.getSelectionStart(); 590 int selectionEnd = textArea.getSelectionEnd(); 591 592 if(selectionStart == selectionEnd) 593 { 594 if(lineHighlight) 595 { 596 gfx.setColor(lineHighlightColor); 597 gfx.fillRect(0,y,getWidth(),height); 598 } 599 } 600 else 601 { 602 gfx.setColor(selectionColor); 603 604 int selectionStartLine = textArea.getSelectionStartLine(); 605 int selectionEndLine = textArea.getSelectionEndLine(); 606 int lineStart = textArea.getLineStartOffset(line); 607 608 int x1, x2; 609 if(textArea.isSelectionRectangular()) 610 { 611 int lineLen = textArea.getLineLength(line); 612 x1 = textArea._offsetToX(line,Math.min(lineLen, 613 selectionStart - textArea.getLineStartOffset( 614 selectionStartLine))); 615 x2 = textArea._offsetToX(line,Math.min(lineLen, 616 selectionEnd - textArea.getLineStartOffset( 617 selectionEndLine))); 618 if(x1 == x2) 619 x2++; 620 } 621 else if(selectionStartLine == selectionEndLine) 622 { 623 x1 = textArea._offsetToX(line, 624 selectionStart - lineStart); 625 x2 = textArea._offsetToX(line, 626 selectionEnd - lineStart); 627 } 628 else if(line == selectionStartLine) 629 { 630 x1 = textArea._offsetToX(line, 631 selectionStart - lineStart); 632 x2 = getWidth(); 633 } 634 else if(line == selectionEndLine) 635 { 636 x1 = 0; 637 x2 = textArea._offsetToX(line, 638 selectionEnd - lineStart); 639 } 640 else 641 { 642 x1 = 0; 643 x2 = getWidth(); 644 } 645 646 gfx.fillRect(x1 > x2 ? x2 : x1,y,x1 > x2 ? 648 (x1 - x2) : (x2 - x1),height); 649 } 650 651 } 652 653 protected void paintBracketHighlight(Graphics gfx, int line, int y) 654 { 655 int position = textArea.getBracketPosition(); 656 if(position == -1) 657 return; 658 y += fm.getLeading() + fm.getMaxDescent(); 659 int x = textArea._offsetToX(line,position); 660 gfx.setColor(bracketHighlightColor); 661 gfx.drawRect(x,y,fm.charWidth('(') - 1, 665 fm.getHeight() - 1); 666 } 667 668 protected void paintCaret(Graphics gfx, int line, int y) 669 { 670 if(textArea.isCaretVisible()) 671 { 672 int offset = textArea.getCaretPosition() 673 - textArea.getLineStartOffset(line); 674 int caretX = textArea._offsetToX(line,offset); 675 int caretWidth = ((blockCaret || 676 textArea.isOverwriteEnabled()) ? 677 fm.charWidth('w') : 1); 678 y += fm.getLeading() + fm.getMaxDescent(); 679 int height = fm.getHeight(); 680 681 gfx.setColor(caretColor); 682 683 if(textArea.isOverwriteEnabled()) 684 { 685 gfx.fillRect(caretX,y + height - 1, 686 caretWidth,1); 687 } 688 else 689 { 690 gfx.drawRect(caretX,y,caretWidth - 1,height - 1); 691 } 692 } 693 } 694 } 695 | Popular Tags |