1 19 20 package org.netbeans.modules.editor.errorstripe; 21 22 import java.awt.Color ; 23 import java.awt.Component ; 24 import java.awt.Cursor ; 25 import java.awt.Dimension ; 26 import java.awt.Graphics ; 27 import java.awt.Insets ; 28 import java.awt.Point ; 29 import java.awt.Rectangle ; 30 import java.awt.event.MouseEvent ; 31 import java.awt.event.MouseListener ; 32 import java.awt.event.MouseMotionListener ; 33 import java.beans.PropertyChangeEvent ; 34 import java.beans.PropertyChangeListener ; 35 import java.text.MessageFormat ; 36 import javax.swing.Icon ; 37 import javax.swing.ImageIcon ; 38 import javax.swing.JComponent ; 39 import javax.swing.JScrollPane ; 40 import javax.swing.SwingUtilities ; 41 import javax.swing.UIManager ; 42 import javax.swing.event.DocumentEvent ; 43 import javax.swing.event.DocumentListener ; 44 import javax.swing.plaf.TextUI ; 45 import javax.swing.text.BadLocationException ; 46 import javax.swing.text.Document ; 47 import javax.swing.text.JTextComponent ; 48 import javax.swing.text.StyledDocument ; 49 import javax.swing.text.View ; 50 import org.netbeans.api.editor.fold.FoldHierarchy; 51 import org.netbeans.api.editor.fold.FoldHierarchyEvent; 52 import org.netbeans.api.editor.fold.FoldHierarchyListener; 53 54 import org.netbeans.editor.BaseDocument; 55 import org.netbeans.editor.BaseTextUI; 56 import org.netbeans.editor.Utilities; 57 import org.netbeans.modules.editor.errorstripe.caret.CaretMark; 58 import org.netbeans.modules.editor.errorstripe.privatespi.Mark; 59 import org.netbeans.spi.editor.errorstripe.UpToDateStatus; 60 import org.openide.ErrorManager; 61 import org.netbeans.modules.editor.errorstripe.privatespi.Status; 62 import org.openide.text.NbDocument; 63 import org.openide.util.NbBundle; 64 import org.openide.util.RequestProcessor; 65 66 67 71 public class AnnotationView extends JComponent implements FoldHierarchyListener, MouseListener , MouseMotionListener , DocumentListener , PropertyChangeListener { 72 73 static final ErrorManager ERR = ErrorManager.getDefault().getInstance("org.netbeans.modules.editor.errorstripe.AnnotationView"); 75 static final ErrorManager TIMING_ERR = ErrorManager.getDefault().getInstance("org.netbeans.modules.editor.errorstripe.AnnotationView.timing"); 77 private static final int STATUS_BOX_SIZE = 7; 78 private static final int THICKNESS = STATUS_BOX_SIZE + 6; 79 static final int PIXELS_FOR_LINE = 3; 80 static final int LINE_SEPARATOR_SIZE = 1; 81 static final int HEIGHT_OFFSET = 20; 82 83 static final int UPPER_HANDLE = 4; 84 static final int LOWER_HANDLE = 4; 85 86 private BaseDocument doc; 87 private JTextComponent pane; 88 89 private static final Color STATUS_UP_PART_COLOR = Color.WHITE; 90 private static final Color STATUS_DOWN_PART_COLOR = new Color (0xCDCABB); 91 92 private static final int QUIET_TIME = 100; 93 94 private final RequestProcessor.Task repaintTask; 95 private final RepaintTask repaintTaskRunnable; 96 97 private AnnotationViewData data; 98 99 private static Icon busyIcon; 100 101 static { 102 busyIcon = new ImageIcon (AnnotationView.class.getResource("resources/hodiny.gif")); 103 } 104 105 109 110 public AnnotationView(JTextComponent pane) { 111 this.pane = pane; 112 113 FoldHierarchy.get(pane).addFoldHierarchyListener(this); 114 115 pane.addPropertyChangeListener(this); 116 117 repaintTask = RequestProcessor.getDefault().create(repaintTaskRunnable = new RepaintTask()); 118 119 data = new AnnotationViewDataImpl(this, pane); 120 121 updateForNewDocument(); 122 123 addMouseListener(this); 124 addMouseMotionListener(this); 125 126 setOpaque(true); 127 128 setToolTipText(org.openide.util.NbBundle.getBundle(AnnotationView.class).getString("TP_ErrorStripe")); 129 } 130 131 AnnotationViewData getData() { 132 return data; 133 } 134 135 private synchronized void updateForNewDocument() { 136 data.unregister(); 137 Document newDocument = pane.getDocument(); 138 139 if (this.doc != null) { 140 this.doc.removeDocumentListener(this); 141 this.doc = null; 142 } 143 144 if (newDocument instanceof BaseDocument) { 145 this.doc = (BaseDocument) pane.getDocument(); 146 this.doc.addDocumentListener(this); 147 } 148 149 data.register(this.doc); 150 } 151 152 int[] getLinesSpan(int currentLine) { 153 double position = modelToView(currentLine); 154 155 if (position == (-1)) 156 return new int[] {currentLine, currentLine}; 157 158 int startLine = currentLine; 159 int endLine = currentLine; 160 161 while (position == modelToView(startLine - 1) && startLine > 0) 162 startLine--; 163 164 while ((endLine + 1) < Utilities.getRowCount(doc) && position == modelToView(endLine + 1)) 165 endLine++; 166 167 return new int[] {startLine, endLine}; 168 } 169 170 private void drawOneColorGlobalStatus(Graphics g, Color color) { 171 g.setColor(color); 172 173 int x = (THICKNESS - STATUS_BOX_SIZE) / 2; 174 int y = (topOffset() - STATUS_BOX_SIZE) / 2; 175 176 g.fillRect(x, y, STATUS_BOX_SIZE, STATUS_BOX_SIZE); 177 178 g.setColor(STATUS_DOWN_PART_COLOR); 179 180 g.drawLine(x - 1, y - 1, x + STATUS_BOX_SIZE, y - 1 ); 181 g.drawLine(x - 1, y - 1, x - 1, y + STATUS_BOX_SIZE); 182 183 g.setColor(STATUS_UP_PART_COLOR); 184 185 g.drawLine(x - 1, y + STATUS_BOX_SIZE, x + STATUS_BOX_SIZE, y + STATUS_BOX_SIZE); 186 g.drawLine(x + STATUS_BOX_SIZE, y - 1, x + STATUS_BOX_SIZE, y + STATUS_BOX_SIZE); 187 } 188 189 private void drawInProgressGlobalStatus(Graphics g, Color color) { 190 int x = (THICKNESS - STATUS_BOX_SIZE) / 2; 191 int y = (topOffset() - STATUS_BOX_SIZE) / 2; 192 193 busyIcon.paintIcon(this, g, x, y); 195 g.setColor(STATUS_DOWN_PART_COLOR); 196 197 g.drawLine(x - 1, y - 1, x + STATUS_BOX_SIZE, y - 1 ); 198 g.drawLine(x - 1, y - 1, x - 1, y + STATUS_BOX_SIZE); 199 200 g.setColor(STATUS_UP_PART_COLOR); 201 202 g.drawLine(x - 1, y + STATUS_BOX_SIZE, x + STATUS_BOX_SIZE, y + STATUS_BOX_SIZE); 203 g.drawLine(x + STATUS_BOX_SIZE, y - 1, x + STATUS_BOX_SIZE, y + STATUS_BOX_SIZE); 204 205 } 206 207 private static final Color GLOBAL_RED = new Color (0xFF2A1C); 208 private static final Color GLOBAL_YELLOW = new Color (0xE1AA00); 209 private static final Color GLOBAL_GREEN = new Color (0x65B56B); 210 211 private Color getColorForGlobalStatus(Status status) { 212 if (Status.STATUS_ERROR == status) 213 return GLOBAL_RED; 214 215 if (Status.STATUS_WARNING == status) 216 return GLOBAL_YELLOW; 217 218 return GLOBAL_GREEN; 219 } 220 221 private void drawGlobalStatus(Graphics g) { 222 UpToDateStatus type = data.computeTotalStatusType(); 223 Color resultingColor; 224 225 if (type == UpToDateStatus.UP_TO_DATE_DIRTY) { 226 drawOneColorGlobalStatus(g, UIManager.getColor("Panel.background")); } else { 228 if (type == UpToDateStatus.UP_TO_DATE_PROCESSING) { 229 drawInProgressGlobalStatus(g, null); 232 } else { 233 if (type == UpToDateStatus.UP_TO_DATE_OK) { 234 Status totalStatus = data.computeTotalStatus(); 235 236 drawOneColorGlobalStatus(g, getColorForGlobalStatus(totalStatus)); 237 } else { 238 throw new IllegalStateException ("Unknown up-to-date type: " + type); } 240 } 241 } 242 } 243 244 private int getCurrentLine() { 245 int offset = pane.getCaretPosition(); Document doc = pane.getDocument(); 247 int line = -1; 248 249 if (doc instanceof StyledDocument ) { 250 line = NbDocument.findLineNumber((StyledDocument ) doc, offset); 251 } 252 253 return line; 254 } 255 256 public void paintComponent(Graphics g) { 257 long startTime = System.currentTimeMillis(); 259 super.paintComponent(g); 260 261 Color oldColor = g.getColor(); 262 263 g.setColor(UIManager.getColor("Panel.background")); 265 g.fillRect(0, 0, getWidth(), getHeight()); 266 267 int currentline = getCurrentLine(); 269 int annotatedLine = data.findNextUsedLine(-1); 270 271 while (annotatedLine != Integer.MAX_VALUE) { 272 int[] lineSpan = getLinesSpan(annotatedLine); 274 int startLine = lineSpan[0]; 275 int endLine = lineSpan[1]; 276 277 Mark m = data.getMainMarkForBlock(startLine, endLine); 278 279 if (m != null) { 280 Status s = m.getStatus(); 281 double start = modelToView(annotatedLine); 282 283 if (s != null) { 284 Color color = m.getEnhancedColor(); 286 287 if (color == null) 288 color = Status.getDefaultColor(s); 289 290 assert color != null; 291 292 g.setColor(color); 293 294 295 if ( m.getType() != Mark.TYPE_CARET ) { 298 g.fillRect(1, (int) start , THICKNESS - 2, PIXELS_FOR_LINE); 299 } 301 if ((startLine <= currentline && currentline <= endLine) || m.getType() == Mark.TYPE_CARET ) { 303 drawCurrentLineMark(g, (int)start); 304 } 305 } 306 } 307 308 annotatedLine = data.findNextUsedLine(endLine); 309 } 310 311 drawGlobalStatus(g); 312 313 g.setColor(oldColor); 314 315 long end = System.currentTimeMillis(); 316 317 if (TIMING_ERR.isLoggable(ErrorManager.INFORMATIONAL)) { 318 TIMING_ERR.log("AnnotationView.paintComponent consumed: " + (end - startTime)); 319 } 320 } 321 322 private void drawCurrentLineMark(Graphics g, int start) { 323 g.setColor( CaretMark.getCaretMarkColor()); 324 g.drawLine(2, start + PIXELS_FOR_LINE / 2, THICKNESS - 3, start + PIXELS_FOR_LINE / 2 ); 325 g.fillRect( THICKNESS / 2 - PIXELS_FOR_LINE / 2, start, PIXELS_FOR_LINE, PIXELS_FOR_LINE ); 326 g.draw3DRect( THICKNESS / 2 - PIXELS_FOR_LINE / 2, start, PIXELS_FOR_LINE - 1, PIXELS_FOR_LINE - 1, true ); 327 328 } 329 330 void fullRepaint() { 331 fullRepaint(false); 332 } 333 334 void fullRepaint(final boolean clearMarksCache) { 335 fullRepaint(clearMarksCache, false); 336 } 337 338 void fullRepaint(final boolean clearMarksCache, final boolean clearModelToViewCache) { 339 synchronized (repaintTaskRunnable) { 340 repaintTaskRunnable.setClearMarksCache(clearMarksCache); 341 repaintTaskRunnable.setClearModelToViewCache(clearModelToViewCache); 342 repaintTask.schedule(QUIET_TIME); 343 } 344 } 345 346 private class RepaintTask implements Runnable { 347 private boolean clearMarksCache; 348 private boolean clearModelToViewCache; 349 350 public void setClearMarksCache(boolean clearMarksCache) { 351 this.clearMarksCache |= clearMarksCache; 352 } 353 354 public void setClearModelToViewCache(boolean clearModelToViewCache) { 355 this.clearModelToViewCache |= clearModelToViewCache; 356 } 357 358 private synchronized boolean readAndDestroyClearMarksCache() { 359 boolean result = clearMarksCache; 360 361 clearMarksCache = false; 362 363 return result; 364 } 365 366 private synchronized boolean readAndDestroyClearModelToViewCache() { 367 boolean result = clearModelToViewCache; 368 369 clearModelToViewCache = false; 370 371 return result; 372 } 373 374 public void run() { 375 final boolean clearMarksCache = readAndDestroyClearMarksCache(); 376 final boolean clearModelToViewCache= readAndDestroyClearModelToViewCache(); 377 378 SwingUtilities.invokeLater(new Runnable () { 380 public void run() { 381 synchronized (AnnotationView.this) { 382 if (clearMarksCache) { 383 data.clear(); 384 } 385 if (clearModelToViewCache) { 386 modelToViewCache = null; 387 } 388 } 389 390 invalidate(); 391 repaint(); 392 } 393 }); 394 } 395 } 396 397 private void documentChange() { 398 fullRepaint(lines != Utilities.getRowCount(doc)); 399 } 400 401 private double getComponentHeight() { 402 return pane.getUI().getRootView(pane).getPreferredSpan(View.Y_AXIS); 403 } 404 405 double getUsableHeight() { 406 Component scrollPaneCandidade = pane.getParent(); 409 410 if (scrollPaneCandidade != null && !(scrollPaneCandidade instanceof JScrollPane )) { 411 scrollPaneCandidade = scrollPaneCandidade.getParent(); 412 } 413 414 Insets scrollBar = UIManager.getInsets("Nb.Editor.ErrorStripe.ScrollBar.Insets"); 416 if (scrollPaneCandidade == null || !(scrollPaneCandidade instanceof JScrollPane ) || scrollBar == null) { 417 return getHeight() - HEIGHT_OFFSET; 419 } 420 421 JScrollPane scrollPane = (JScrollPane ) scrollPaneCandidade; 422 int visibleHeight = scrollPane.getViewport().getExtentSize().height; 423 424 int topButton = topOffset(); 425 int bottomButton = scrollBar.bottom; 426 427 return visibleHeight - topButton - bottomButton; 428 } 429 430 int topOffset() { 431 Insets scrollBar = UIManager.getInsets("Nb.Editor.ErrorStripe.ScrollBar.Insets"); 433 if (scrollBar == null) { 434 return HEIGHT_OFFSET; 436 } 437 438 return (HEIGHT_OFFSET > scrollBar.top ? HEIGHT_OFFSET : scrollBar.top) + PIXELS_FOR_LINE; 439 } 440 441 private int[] modelToViewCache = null; 442 private int lines = -1; 443 private int height = -1; 444 445 private int getYFromPos(int offset) throws BadLocationException { 446 TextUI ui = pane.getUI(); 447 int result; 448 449 if (ui instanceof BaseTextUI) { 450 result = ((BaseTextUI) ui).getYFromPos(offset); 451 } else { 452 Rectangle r = pane.modelToView(offset); 453 454 result = r != null ? r.y : 0; 455 } 456 457 if (result == 0) { 458 return -1; 459 } else { 460 return result; 461 } 462 } 463 464 private synchronized int getModelToViewImpl(int line) throws BadLocationException { 465 int docLines = Utilities.getRowCount(doc); 466 467 if (modelToViewCache == null || height != pane.getHeight() || lines != docLines) { 468 modelToViewCache = new int[Utilities.getRowCount(doc) + 2]; 469 lines = Utilities.getRowCount(doc); 470 height = pane.getHeight(); 471 } 472 473 if (line >= docLines) 474 return -1; 475 476 int result = modelToViewCache[line + 1]; 477 478 if (result == 0) { 479 int lineOffset = Utilities.getRowStartFromLineOffset((BaseDocument) pane.getDocument(), line); 480 481 modelToViewCache[line + 1] = result = getYFromPos(lineOffset); 482 } 483 484 if (result == (-1)) 485 result = 0; 486 487 return result; 488 } 489 490 double modelToView(int line) { 491 try { 492 int r = getModelToViewImpl(line); 493 494 if (r == (-1)) 495 return -1.0; 496 497 if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) { 498 ERR.log(ErrorManager.INFORMATIONAL, "AnnotationView.modelToView: line=" + line); ERR.log(ErrorManager.INFORMATIONAL, "AnnotationView.modelToView: r=" + r); ERR.log(ErrorManager.INFORMATIONAL, "AnnotationView.modelToView: getComponentHeight()=" + getComponentHeight()); ERR.log(ErrorManager.INFORMATIONAL, "AnnotationView.modelToView: getUsableHeight()=" + getUsableHeight()); } 504 505 if (getComponentHeight() <= getUsableHeight()) { 506 return r + topOffset(); 508 } else { 509 double position = r / getComponentHeight(); 510 int blocksCount = (int) (getUsableHeight() / (PIXELS_FOR_LINE + LINE_SEPARATOR_SIZE)); 511 int block = (int) (position * blocksCount); 512 513 return block * (PIXELS_FOR_LINE + LINE_SEPARATOR_SIZE) + topOffset(); 514 } 515 } catch (BadLocationException e) { 516 ErrorManager.getDefault().notify(e); 517 return -1.0; 518 } 519 } 520 521 private static final int VIEW_TO_MODEL_IMPORTANCE = ErrorManager.INFORMATIONAL; 522 523 int[] viewToModel(double offset) { 524 try { 525 if (getComponentHeight() <= getUsableHeight()) { 526 int positionOffset = pane.viewToModel(new Point (1, (int) (offset - topOffset()))); 528 int line = Utilities.getLineOffset(doc, positionOffset); 529 530 if (ERR.isLoggable(VIEW_TO_MODEL_IMPORTANCE)) { 531 ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: line=" + line); } 533 534 double position = modelToView(line); 535 536 if (offset < position || offset >= (position + PIXELS_FOR_LINE)) 537 return null; 538 539 return getLinesSpan(line); 540 } else { 541 int blocksCount = (int) (getUsableHeight() / (PIXELS_FOR_LINE + LINE_SEPARATOR_SIZE)); 542 int block = (int) ((offset - topOffset()) / (PIXELS_FOR_LINE + LINE_SEPARATOR_SIZE)); 543 double yPos = (getComponentHeight() * block) / blocksCount; 544 545 if (yPos == (int) yPos) 546 yPos -= 1; 547 548 int positionOffset = pane.viewToModel(new Point (0, (int) yPos)); 549 int line = Utilities.getLineOffset(doc, positionOffset) + 1; 550 int[] span = getLinesSpan(line); 551 double normalizedOffset = modelToView(span[0]); 552 553 if (ERR.isLoggable(VIEW_TO_MODEL_IMPORTANCE)) { 554 ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: offset=" + offset); ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: block=" + block); ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: blocksCount=" + blocksCount); ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: pane.getHeight()=" + pane.getHeight()); ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: yPos=" + yPos); ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: positionOffset=" + positionOffset); ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: line=" + line); ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: normalizedOffset=" + normalizedOffset); } 563 564 if (offset < normalizedOffset || offset >= (normalizedOffset + PIXELS_FOR_LINE)) { 565 return null; 566 } 567 568 if (block < 0) 569 return null; 570 571 return span; 572 } 573 } catch (BadLocationException e) { 574 ErrorManager.getDefault().notify(e); 575 return null; 576 } 577 } 578 579 private Mark getMarkForPointImpl(double point) { 580 int[] lineSpan = viewToModel(point); 581 582 if (lineSpan == null) 583 return null; 584 585 int startLine = lineSpan[0]; 586 int endLine = lineSpan[1]; 587 588 if (startLine != (-1)) { 589 return data.getMainMarkForBlock(startLine, endLine); 590 } 591 592 return null; 593 } 594 595 Mark getMarkForPoint(double point) { 596 point = ((int) (point / (PIXELS_FOR_LINE + LINE_SEPARATOR_SIZE))) * (PIXELS_FOR_LINE + LINE_SEPARATOR_SIZE); 598 599 Mark a = getMarkForPointImpl(point); 600 601 if (ERR.isLoggable(VIEW_TO_MODEL_IMPORTANCE)) { 602 ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.getAnnotationForPoint: point=" + point); ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.getAnnotationForPoint: a=" + a); } 605 606 int relativeMax = Math.max(UPPER_HANDLE + 1, LOWER_HANDLE + 1); 607 608 for (short relative = 1; relative < relativeMax && a == null; relative++) { 609 if (relative <= UPPER_HANDLE) { 610 a = getMarkForPointImpl(point + relative); 611 612 if (ERR.isLoggable(VIEW_TO_MODEL_IMPORTANCE)) { 613 ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.getAnnotationForPoint: a=" + a); ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.getAnnotationForPoint: relative=" + relative); } 616 } 617 618 if (relative <= LOWER_HANDLE && a == null) { 619 a = getMarkForPointImpl(point - relative); 620 621 if (ERR.isLoggable(VIEW_TO_MODEL_IMPORTANCE)) { 622 ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.getAnnotationForPoint: a=" + a); ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.getAnnotationForPoint: relative=-" + relative); } 625 } 626 } 627 628 return a; 629 } 630 631 public Dimension getMaximumSize() { 632 return new Dimension (THICKNESS, Integer.MAX_VALUE); 633 } 634 635 public Dimension getMinimumSize() { 636 return new Dimension (THICKNESS, Integer.MIN_VALUE); 637 } 638 639 public Dimension getPreferredSize() { 640 return new Dimension (THICKNESS, Integer.MAX_VALUE); 641 } 642 643 public void mouseReleased(MouseEvent e) { 644 resetCursor(); 646 } 647 648 public void mousePressed(MouseEvent e) { 649 resetCursor(); 650 } 651 652 public void mouseMoved(MouseEvent e) { 653 checkCursor(e); 654 } 655 656 public void mouseExited(MouseEvent e) { 657 resetCursor(); 658 } 659 660 public void mouseEntered(MouseEvent e) { 661 checkCursor(e); 662 } 663 664 public void mouseDragged(MouseEvent e) { 665 } 666 667 public void mouseClicked(MouseEvent e) { 668 resetCursor(); 669 670 Mark mark = getMarkForPoint(e.getPoint().getY()); 671 672 if (mark!= null) { 673 pane.setCaretPosition(Utilities.getRowStartFromLineOffset(doc, mark.getAssignedLines()[0])); 674 } 675 } 676 677 private void resetCursor() { 678 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 679 } 680 681 private void checkCursor(MouseEvent e) { 682 Mark mark = getMarkForPoint(e.getPoint().getY()); 683 684 if (mark == null) { 685 resetCursor(); 686 return ; 687 } 688 689 setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 690 } 691 692 public String getToolTipText(MouseEvent event) { 693 if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) { 694 ERR.log(ErrorManager.INFORMATIONAL, "getToolTipText: event=" + event); } 696 int y = event.getY(); 697 698 if (y <= topOffset()) { 699 int[] errWar = data.computeErrorsAndWarnings(); 700 int errors = errWar[0]; 701 int warnings = errWar[1]; 702 703 if (errors == 0 && warnings == 0) { 704 return NbBundle.getBundle(AnnotationView.class).getString("TP_NoErrors"); } 706 707 if (errors == 0 && warnings != 0) { 708 return MessageFormat.format(NbBundle.getBundle(AnnotationView.class).getString("TP_X_warning(s)"), new Object [] {new Integer (warnings)}); } 710 711 if (errors != 0 && warnings == 0) { 712 return MessageFormat.format(NbBundle.getBundle(AnnotationView.class).getString("TP_X_error(s)"), new Object [] {new Integer (errors)}); } 714 715 return MessageFormat.format(NbBundle.getBundle(AnnotationView.class).getString("TP_X_error(s)_Y_warning(s)"), new Object [] {new Integer (errors), new Integer (warnings)}); } 717 718 Mark mark = getMarkForPoint(y); 719 720 if (mark != null) { 721 String description = mark.getShortDescription(); 722 723 if (description != null) { 724 return "<html><body>" + translate(description); } 726 } 727 728 return null; 729 } 730 731 private static String [] c = new String [] {"&", "<", ">", "\n", "\""}; private static String [] tags = new String [] {"&", "<", ">", "<br>", """}; 734 private String translate(String input) { 735 for (int cntr = 0; cntr < c.length; cntr++) { 736 input = input.replaceAll(c[cntr], tags[cntr]); 737 } 738 739 return input; 740 } 741 742 public void foldHierarchyChanged(FoldHierarchyEvent evt) { 743 fullRepaint(false, true); 746 } 747 748 public void removeUpdate(DocumentEvent e) { 749 documentChange(); 750 } 751 752 public void insertUpdate(DocumentEvent e) { 753 documentChange(); 754 } 755 756 public void changedUpdate(DocumentEvent e) { 757 } 759 760 public void propertyChange(PropertyChangeEvent evt) { 761 if (evt.getSource() == this.pane && "document".equals(evt.getPropertyName())) { 762 updateForNewDocument(); 763 return ; 764 } 765 766 fullRepaint(); 767 } 768 769 } 770 | Popular Tags |