1 19 20 package org.netbeans.modules.versioning.system.cvss.ui.actions.annotate; 21 22 import org.netbeans.editor.*; 23 import org.netbeans.editor.Utilities; 24 import org.netbeans.api.editor.fold.*; 25 import org.netbeans.api.diff.*; 26 import org.netbeans.api.project.*; 27 import org.netbeans.api.project.ui.OpenProjects; 28 import org.netbeans.modules.versioning.system.cvss.ui.actions.log.*; 29 import org.netbeans.modules.versioning.system.cvss.ui.actions.diff.*; 30 import org.netbeans.modules.versioning.system.cvss.ui.actions.update.GetCleanAction; 31 import org.netbeans.modules.versioning.system.cvss.util.*; 32 import org.netbeans.lib.cvsclient.command.annotate.*; 33 import org.netbeans.spi.diff.*; 34 import org.openide.*; 35 import org.openide.loaders.*; 36 import org.openide.filesystems.*; 37 import org.openide.text.*; 38 import org.openide.util.*; 39 import org.openide.xml.*; 40 41 import javax.swing.*; 42 import javax.swing.Timer ; 43 import javax.swing.event.*; 44 import javax.swing.text.*; 45 import javax.accessibility.Accessible ; 46 import java.awt.*; 47 import java.awt.event.*; 48 import java.beans.*; 49 import java.util.*; 50 import java.util.List ; 51 import java.io.*; 52 import java.text.MessageFormat ; 53 54 66 final class AnnotationBar extends JComponent implements Accessible , PropertyChangeListener, LogOutputListener, DocumentListener, ChangeListener, ActionListener, Runnable , ComponentListener { 67 68 71 private final JTextComponent textComponent; 72 73 76 private final EditorUI editorUI; 77 78 81 private final FoldHierarchy foldHierarchy; 82 83 86 private final BaseDocument doc; 87 88 91 private final Caret caret; 92 93 97 private Timer caretTimer; 98 99 102 private boolean annotated; 103 104 113 private Map elementAnnotations; 114 115 119 private Map commitMessages; 120 121 125 private String elementAnnotationsSubstitute; 126 127 private Color backgroundColor = Color.WHITE; 128 private Color foregroundColor = Color.BLACK; 129 private Color selectedColor = Color.BLUE; 130 131 134 private String recentStatusMessage; 135 136 139 private String recentRevision; 140 141 144 RequestProcessor requestProcessor = null; 145 146 149 private RequestProcessor.Task latestAnnotationTask = null; 150 151 154 public AnnotationBar(JTextComponent target) { 155 this.textComponent = target; 156 this.editorUI = Utilities.getEditorUI(target); 157 this.foldHierarchy = FoldHierarchy.get(editorUI.getComponent()); 158 this.doc = editorUI.getDocument(); 159 this.caret = textComponent.getCaret(); 160 } 161 162 164 169 public void annotate() { 170 annotated = true; 171 elementAnnotations = null; 172 commitMessages = null; 173 ResourceBundle loc = NbBundle.getBundle(AnnotationBar.class); 174 elementAnnotationsSubstitute = loc.getString("CTL_AnnotationSubstitute"); 175 176 doc.addDocumentListener(this); 177 textComponent.addComponentListener(this); 178 editorUI.addPropertyChangeListener(this); 179 180 revalidate(); } 182 183 187 public void annotationLines(File file, List annotateLines) { 188 List lines = new LinkedList(annotateLines); 189 int lineCount = lines.size(); 190 191 int ann2editorPermutation[] = new int[lineCount]; 192 for (int i = 0; i< lineCount; i++) { 193 ann2editorPermutation[i] = i+1; 194 } 195 196 DiffProvider diff = (DiffProvider) Lookup.getDefault().lookup(DiffProvider.class); 197 if (diff != null) { 198 Reader r = new LinesReader(lines); 199 Reader docReader = org.netbeans.modules.versioning.util.Utils.getDocumentReader(doc); 200 try { 201 202 Difference[] differences = diff.computeDiff(r, docReader); 203 204 207 for (int i = 0; i < differences.length; i++) { 208 Difference d = differences[i]; 209 if (d.getType() == Difference.ADD) continue; 210 211 int editorStart; 212 int firstShift = d.getFirstEnd() - d.getFirstStart() +1; 213 if (d.getType() == Difference.CHANGE) { 214 int firstLen = d.getFirstEnd() - d.getFirstStart(); 215 int secondLen = d.getSecondEnd() - d.getSecondStart(); 216 if (secondLen >= firstLen) continue; editorStart = d.getSecondStart(); 218 firstShift = firstLen - secondLen; 219 } else { editorStart = d.getSecondStart() + 1; 221 } 222 223 for (int c = editorStart + firstShift -1; c<lineCount; c++) { 224 ann2editorPermutation[c] -= firstShift; 225 } 226 } 227 228 for (int i = differences.length -1; i >= 0; i--) { 229 Difference d = differences[i]; 230 if (d.getType() == Difference.DELETE) continue; 231 232 int firstStart; 233 int firstShift = d.getSecondEnd() - d.getSecondStart() +1; 234 if (d.getType() == Difference.CHANGE) { 235 int firstLen = d.getFirstEnd() - d.getFirstStart(); 236 int secondLen = d.getSecondEnd() - d.getSecondStart(); 237 if (secondLen <= firstLen) continue; firstShift = secondLen - firstLen; 239 firstStart = d.getFirstStart(); 240 } else { 241 firstStart = d.getFirstStart() + 1; 242 } 243 244 for (int k = firstStart-1; k<lineCount; k++) { 245 ann2editorPermutation[k] += firstShift; 246 } 247 } 248 249 } catch (IOException e) { 250 ErrorManager err = ErrorManager.getDefault(); 251 err.annotate(e, "Cannot compute local diff required for annotations, ignoring..."); err.notify(ErrorManager.INFORMATIONAL, e); 253 } 254 } 255 256 try { 257 doc.atomicLock(); 258 StyledDocument sd = (StyledDocument) doc; 259 Iterator it = lines.iterator(); 260 elementAnnotations = Collections.synchronizedMap(new HashMap(lines.size())); 261 while (it.hasNext()) { 262 AnnotateLine line = (AnnotateLine) it.next(); 263 int lineNum = ann2editorPermutation[line.getLineNum() -1]; 264 try { 265 int lineOffset = NbDocument.findLineOffset(sd, lineNum -1); 266 Element element = sd.getParagraphElement(lineOffset); 267 elementAnnotations.put(element, line); 268 } catch (IndexOutOfBoundsException ex) { 269 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); 272 } 273 } 274 } finally { 275 doc.atomicUnlock(); 276 } 277 278 caret.addChangeListener(this); 280 this.caretTimer = new Timer (500, this); 281 caretTimer.setRepeats(false); 282 283 onCurrentLine(); 284 revalidate(); 285 repaint(); 286 } 287 288 293 public void commitMessages(Map messages) { 294 this.commitMessages = messages; 295 } 296 297 299 305 private File getCurrentFile() { 306 File result = null; 307 308 DataObject dobj = (DataObject)doc.getProperty(Document.StreamDescriptionProperty); 309 if (dobj != null) { 310 FileObject fo = dobj.getPrimaryFile(); 311 result = FileUtil.toFile(fo); 312 } 313 314 return result; 315 } 316 317 321 public void addNotify() { 322 super.addNotify(); 323 324 325 this.addMouseListener(new MouseAdapter() { 326 public void mousePressed(MouseEvent e) { 327 maybeShowPopup(e); 328 } 329 330 public void mouseReleased(MouseEvent e) { 331 maybeShowPopup(e); 332 } 333 334 private void maybeShowPopup(MouseEvent e) { 335 if (e.isPopupTrigger()) { 336 createPopup().show(e.getComponent(), 337 e.getX(), e.getY()); 338 } 339 } 340 }); 341 342 setToolTipText(""); 345 } 346 347 private JPopupMenu createPopup() { 348 final ResourceBundle loc = NbBundle.getBundle(AnnotationBar.class); 349 final JPopupMenu popupMenu = new JPopupMenu(); 350 final JMenuItem diffMenu = new JMenuItem(loc.getString("CTL_MenuItem_DiffToRevision")); 351 diffMenu.addActionListener(new ActionListener() { 352 public void actionPerformed(ActionEvent e) { 353 if (recentRevision != null) { 354 String prevRevision = Utils.previousRevision(recentRevision); 355 if (prevRevision != null) { 356 File file = getCurrentFile(); 357 if (file != null) { 358 DiffExecutor diffExecutor = new DiffExecutor(file.getName()); 359 diffExecutor.showDiff(file, prevRevision, recentRevision); 360 } 361 } 362 } 363 } 364 }); 365 popupMenu.add(diffMenu); 366 367 final JMenuItem rollbackMenu = new JMenuItem(loc.getString("CTL_MenuItem_RollbackToRevision")); 368 rollbackMenu.addActionListener(new ActionListener() { 369 public void actionPerformed(ActionEvent e) { 370 File file = getCurrentFile(); 371 GetCleanAction.rollback(file, recentRevision); 372 } 373 }); 374 popupMenu.add(rollbackMenu); 375 376 Project prj = Utils.getProject(getCurrentFile()); 377 if (prj != null) { 378 String prjName = ProjectUtils.getInformation(prj).getDisplayName(); 379 JMenuItem menu = new JMenuItem(NbBundle.getMessage(AnnotationBar.class, "CTL_MenuItem_FindCommitInProject", prjName)); 380 menu.addActionListener(new ActionListener() { 381 public void actionPerformed(ActionEvent e) { 382 int line = getCurrentLine(); 383 if (line == -1) return; 384 AnnotateLine al = getAnnotateLine(line); 385 if (al == null || commitMessages == null) return; 386 String message = (String ) commitMessages.get(al.getRevision()); 387 File file = getCurrentFile(); 388 Project project = Utils.getProject(file); 389 Context context = Utils.getProjectsContext(new Project[] { project }); 390 SearchHistoryAction.openSearch( 391 context, 392 ProjectUtils.getInformation(project).getDisplayName(), 393 message, al.getAuthor(), al.getDate()); 394 } 395 }); 396 popupMenu.add(menu); 397 } 398 399 JMenuItem menu = new JMenuItem(loc.getString("CTL_MenuItem_FindCommitInProjects")); 400 menu.addActionListener(new ActionListener() { 401 public void actionPerformed(ActionEvent e) { 402 int line = getCurrentLine(); 403 if (line == -1) return; 404 AnnotateLine al = getAnnotateLine(line); 405 if (al == null || commitMessages == null) return; 406 String message = (String ) commitMessages.get(al.getRevision()); 407 Project [] projects = OpenProjects.getDefault().getOpenProjects(); 408 int n = projects.length; 409 SearchHistoryAction.openSearch( 410 (n == 1) ? ProjectUtils.getInformation(projects[0]).getDisplayName() : 411 NbBundle.getMessage(AnnotationBar.class, "CTL_FindAssociateChanges_OpenProjects_Title", Integer.toString(n)), 412 message, al.getAuthor(), al.getDate()); 413 } 414 }); 415 popupMenu.add(menu); 416 417 menu = new JMenuItem(loc.getString("CTL_MenuItem_CloseAnnotations")); 418 menu.addActionListener(new ActionListener() { 419 public void actionPerformed(ActionEvent e) { 420 hideBar(); 421 } 422 }); 423 popupMenu.add(new JSeparator()); 424 popupMenu.add(menu); 425 426 428 diffMenu.setVisible(false); 429 rollbackMenu.setVisible(false); 430 if (recentRevision != null) { 431 String prevRevision = Utils.previousRevision(recentRevision); 432 if (prevRevision != null) { 433 String format = loc.getString("CTL_MenuItem_DiffToRevision"); 434 diffMenu.setText(MessageFormat.format(format, new Object [] { recentRevision, prevRevision })); 435 diffMenu.setVisible(true); 436 } 437 String format = loc.getString("CTL_MenuItem_RollbackToRevision"); 438 rollbackMenu.setText(MessageFormat.format(format, new Object [] { recentRevision })); 439 rollbackMenu.setVisible(true); 440 } 441 442 return popupMenu; 443 } 444 445 448 void hideBar() { 449 annotated = false; 450 revalidate(); 451 release(); 452 } 453 454 461 private int getCurrentLine() { 462 int result = 0; 463 464 int offset = caret.getDot(); 465 try { 466 result = Utilities.getLineOffset(doc, offset); 467 } catch (BadLocationException ex) { 468 result = -1; 469 } 470 471 return result; 472 } 473 476 private RequestProcessor getRequestProcessor() { 477 if (requestProcessor == null) { 478 requestProcessor = new RequestProcessor("AnnotationBarRP", 1, true); } 480 481 return requestProcessor; 482 } 483 484 489 private void onCurrentLine() { 490 if (latestAnnotationTask != null) { 491 latestAnnotationTask.cancel(); 492 } 493 494 latestAnnotationTask = getRequestProcessor().post(this); 495 } 496 497 public void run() { 499 ResourceBundle loc = NbBundle.getBundle(AnnotationBar.class); 501 StatusBar statusBar = editorUI.getStatusBar(); 503 recentStatusMessage = loc.getString("CTL_StatusBar_WaitFetchAnnotation"); 504 statusBar.setText(StatusBar.CELL_MAIN, recentStatusMessage); 505 506 int line = -1; 508 int offset = caret.getDot(); 509 try { 510 line = Utilities.getLineOffset(doc, offset); 511 } catch (BadLocationException ex) { 512 ErrorManager err = ErrorManager.getDefault(); 513 err.annotate(ex, "Can not get line for caret at offset " + offset); err.notify(ex); 515 clearRecentFeedback(); 516 return; 517 } 518 519 AnnotateLine al = getAnnotateLine(line); 521 if (al == null) { 522 AnnotationMarkProvider amp = AnnotationMarkInstaller.getMarkProvider(textComponent); 523 if (amp != null) { 524 amp.setMarks(Collections.EMPTY_LIST); 525 } 526 clearRecentFeedback(); 527 if (recentRevision != null) { 528 recentRevision = null; 529 repaint(); 530 } 531 return; 532 } 533 534 String revision = al.getRevision(); 536 if (revision.equals(recentRevision) == false) { 537 recentRevision = revision; 538 repaint(); 539 540 AnnotationMarkProvider amp = AnnotationMarkInstaller.getMarkProvider(textComponent); 541 if (amp != null) { 542 543 List marks = new ArrayList(elementAnnotations.size()); 544 Iterator it2; 547 synchronized(elementAnnotations) { 548 it2 = new HashSet(elementAnnotations.entrySet()).iterator(); 549 } 550 while (it2.hasNext()) { 551 Map.Entry next = (Map.Entry) it2.next(); 552 AnnotateLine annotateLine = (AnnotateLine) next.getValue(); 553 if (revision.equals(annotateLine.getRevision())) { 554 Element element = (Element) next.getKey(); 555 if (elementAnnotations.containsKey(element) == false) { 556 continue; 557 } 558 int elementOffset = element.getStartOffset(); 559 int lineNumber = NbDocument.findLineNumber((StyledDocument)doc, elementOffset); 560 AnnotationMark mark = new AnnotationMark(lineNumber, revision); 561 marks.add(mark); 562 } 563 564 if (Thread.interrupted()) { 565 clearRecentFeedback(); 566 return; 567 } 568 } 569 amp.setMarks(marks); 570 } 571 } 572 573 if (commitMessages != null) { 574 String message = (String ) commitMessages.get(revision); 575 if (message != null) { 576 recentStatusMessage = message; 577 statusBar.setText(StatusBar.CELL_MAIN, al.getAuthor() + ": " + recentStatusMessage); } else { 579 clearRecentFeedback(); 580 } 581 } else { 582 clearRecentFeedback(); 583 }; 584 } 585 586 590 private void clearRecentFeedback() { 591 StatusBar statusBar = editorUI.getStatusBar(); 592 if (statusBar.getText(StatusBar.CELL_MAIN) == recentStatusMessage) { 593 statusBar.setText(StatusBar.CELL_MAIN, ""); } 595 } 596 597 606 public Dimension getPreferredSize() { 607 Dimension dim = textComponent.getSize(); 608 int width = annotated ? getBarWidth() : 0; 609 dim.width = width; 610 dim.height *=2; return dim; 612 } 613 614 619 public Dimension getMaximumSize() { 620 return getPreferredSize(); 621 } 622 623 628 private int getBarWidth() { 629 String longestString = ""; if (elementAnnotations == null) { 631 longestString = elementAnnotationsSubstitute; 632 } else { 633 synchronized(elementAnnotations) { 634 Iterator it = elementAnnotations.values().iterator(); 635 while (it.hasNext()) { 636 AnnotateLine line = (AnnotateLine) it.next(); 637 String displayName = line.getRevision() + " " + line.getAuthor(); if (displayName.length() > longestString.length()) { 639 longestString = displayName; 640 } 641 } 642 } 643 } 644 char[] data = longestString.toCharArray(); 645 int w = getGraphics().getFontMetrics().charsWidth(data, 0, data.length); 646 return w; 647 } 648 649 653 private void release() { 654 editorUI.removePropertyChangeListener(this); 655 textComponent.removeComponentListener(this); 656 doc.removeDocumentListener(this); 657 caret.removeChangeListener(this); 658 if (caretTimer != null) { 659 caretTimer.removeActionListener(this); 660 } 661 commitMessages = null; 662 elementAnnotations = null; 663 if(latestAnnotationTask != null) { 665 latestAnnotationTask.cancel(); 666 } 667 AnnotationMarkProvider amp = AnnotationMarkInstaller.getMarkProvider(textComponent); 668 if (amp != null) { 669 amp.setMarks(Collections.EMPTY_LIST); 670 } 671 672 clearRecentFeedback(); 673 } 674 675 679 private void paintView(View view, Graphics g, int yBase) { 680 JTextComponent component = editorUI.getComponent(); 681 if (component == null) return; 682 BaseTextUI textUI = (BaseTextUI)component.getUI(); 683 684 Element rootElem = textUI.getRootView(component).getElement(); 685 int line = rootElem.getElementIndex(view.getStartOffset()); 686 687 String annotation = ""; AnnotateLine al = null; 689 if (elementAnnotations != null) { 690 al = getAnnotateLine(line); 691 if (al != null) { 692 annotation = al.getRevision() + " " + al.getAuthor(); } 694 } else { 695 annotation = elementAnnotationsSubstitute; 696 } 697 698 if (al != null && al.getRevision().equals(recentRevision)) { 699 g.setColor(selectedColor()); 700 } else { 701 g.setColor(foregroundColor()); 702 } 703 g.drawString(annotation, 0, yBase + editorUI.getLineAscent()); 704 } 705 706 709 public String getToolTipText (MouseEvent e) { 710 if (editorUI == null) 711 return null; 712 int line = getLineFromMouseEvent(e); 713 714 StringBuffer annotation = new StringBuffer (); 715 if (elementAnnotations != null) { 716 AnnotateLine al = getAnnotateLine(line); 717 718 if (al != null) { 719 String escapedAuthor = NbBundle.getMessage(AnnotationBar.class, "BK0001"); 720 try { 721 escapedAuthor = XMLUtil.toElementContent(al.getAuthor()); 722 } catch (CharConversionException e1) { 723 ErrorManager err = ErrorManager.getDefault(); 724 err.annotate(e1, "CVS.AB: can not HTML escape: " + al.getAuthor()); err.notify(ErrorManager.INFORMATIONAL, e1); 726 } 727 728 annotation.append("<html><!-- line=" + line++ + " -->" + al.getRevision() + " <b>" + escapedAuthor + "</b> " + al.getDateString()); if (commitMessages != null) { 731 String message = (String ) commitMessages.get(al.getRevision()); 732 if (message != null) { 733 String escaped = null; 734 try { 735 escaped = XMLUtil.toElementContent(message); 736 } catch (CharConversionException e1) { 737 ErrorManager err = ErrorManager.getDefault(); 738 err.annotate(e1, "CVS.AB: can not HTML escape: " + message); err.notify(ErrorManager.INFORMATIONAL, e1); 740 } 741 if (escaped != null) { 742 String lined = escaped.replaceAll(System.getProperty("line.separator"), "<br>"); annotation.append("<p>" + lined); } 745 } 746 } 747 } 748 } else { 749 annotation.append(elementAnnotationsSubstitute); 750 } 751 752 return annotation.toString(); 753 } 754 755 767 private AnnotateLine getAnnotateLine(int line) { 768 StyledDocument sd = (StyledDocument) doc; 769 int lineOffset = NbDocument.findLineOffset(sd, line); 770 Element element = sd.getParagraphElement(lineOffset); 771 AnnotateLine al = (AnnotateLine) elementAnnotations.get(element); 772 773 if (al != null) { 774 int startOffset = element.getStartOffset(); 775 int endOffset = element.getEndOffset(); 776 try { 777 int len = endOffset - startOffset; 778 String text = doc.getText(startOffset, len -1); 779 String content = al.getContent(); 780 if (text.equals(content)) { 781 return al; 782 } 783 } catch (BadLocationException e) { 784 ErrorManager err = ErrorManager.getDefault(); 785 err.annotate(e, "CVS.AB: can not locate line annotation."); err.notify(ErrorManager.INFORMATIONAL, e); 787 } 788 } 789 790 return null; 791 } 792 793 798 public void paintComponent(Graphics g) { 799 super.paintComponent(g); 800 801 Rectangle clip = g.getClipBounds(); 802 803 JTextComponent component = editorUI.getComponent(); 804 if (component == null) return; 805 806 BaseTextUI textUI = (BaseTextUI)component.getUI(); 807 View rootView = Utilities.getDocumentView(component); 808 if (rootView == null) return; 809 810 g.setColor(backgroundColor()); 811 g.fillRect(clip.x, clip.y, clip.width, clip.height); 812 813 AbstractDocument doc = (AbstractDocument)component.getDocument(); 814 doc.readLock(); 815 try{ 816 foldHierarchy.lock(); 817 try{ 818 int startPos = textUI.getPosFromY(clip.y); 819 int startViewIndex = rootView.getViewIndex(startPos,Position.Bias.Forward); 820 int rootViewCount = rootView.getViewCount(); 821 822 if (startViewIndex >= 0 && startViewIndex < rootViewCount) { 823 Rectangle rec = textUI.modelToView(component, rootView.getView(startViewIndex).getStartOffset()); 825 int y = (rec == null) ? 0 : rec.y; 826 827 int clipEndY = clip.y + clip.height; 828 for (int i = startViewIndex; i < rootViewCount; i++){ 829 View view = rootView.getView(i); 830 paintView(view, g, y); 831 y += editorUI.getLineHeight(); 832 if (y >= clipEndY) { 833 break; 834 } 835 } 836 } 837 838 } finally { 839 foldHierarchy.unlock(); 840 } 841 } catch (BadLocationException ble){ 842 ErrorManager.getDefault().notify(ble); 843 } finally { 844 doc.readUnlock(); 845 } 846 } 847 848 private Color backgroundColor() { 849 if (textComponent != null) { 850 return textComponent.getBackground(); 851 } 852 return backgroundColor; 853 } 854 855 private Color foregroundColor() { 856 if (textComponent != null) { 857 return textComponent.getForeground(); 858 } 859 return foregroundColor; 860 } 861 862 private Color selectedColor() { 863 if (backgroundColor == backgroundColor()) { 864 return selectedColor; 865 } 866 if (textComponent != null) { 867 return textComponent.getForeground(); 868 } 869 return selectedColor; 870 871 } 872 873 874 875 private int getLineFromMouseEvent(MouseEvent e){ 876 int line = -1; 877 if (editorUI != null) { 878 try{ 879 JTextComponent component = editorUI.getComponent(); 880 BaseTextUI textUI = (BaseTextUI)component.getUI(); 881 int clickOffset = textUI.viewToModel(component, new Point(0, e.getY())); 882 line = Utilities.getLineOffset(doc, clickOffset); 883 }catch (BadLocationException ble){ 884 } 885 } 886 return line; 887 } 888 889 890 public void propertyChange(PropertyChangeEvent evt) { 891 if (evt == null) return; 892 String id = evt.getPropertyName(); 893 if (EditorUI.COMPONENT_PROPERTY.equals(id)) { if (evt.getNewValue() == null){ 895 release(); 897 } 898 } 899 900 } 901 902 903 public void changedUpdate(DocumentEvent e) { 904 } 905 906 907 public void insertUpdate(DocumentEvent e) { 908 if (elementAnnotations != null) { 914 Element[] elements = e.getDocument().getRootElements(); 915 synchronized(elementAnnotations) { for (int i = 0; i < elements.length; i++) { 917 Element element = elements[i]; 918 DocumentEvent.ElementChange change = e.getChange(element); 919 if (change == null) continue; 920 Element[] removed = change.getChildrenRemoved(); 921 Element[] added = change.getChildrenAdded(); 922 923 if (removed.length == added.length) { 924 for (int c = 0; c<removed.length; c++) { 925 Object recent = elementAnnotations.get(removed[c]); 926 if (recent != null) { 927 elementAnnotations.remove(removed[c]); 928 elementAnnotations.put(added[c], recent); 929 } 930 } 931 } else if (removed.length == 1 && added.length > 0) { 932 Element key = removed[0]; 933 Object recent = elementAnnotations.get(key); 934 if (recent != null) { 935 elementAnnotations.remove(key); 936 elementAnnotations.put(added[0], recent); 937 } 938 } 939 } 940 } 941 } 942 repaint(); 943 } 944 945 946 public void removeUpdate(DocumentEvent e) { 947 if (e.getDocument().getLength() == 0) { hideBar(); 949 } 950 repaint(); 951 } 952 953 954 public void stateChanged(ChangeEvent e) { 955 assert e.getSource() == caret; 956 caretTimer.restart(); 957 } 958 959 960 public void actionPerformed(ActionEvent e) { 961 assert e.getSource() == caretTimer; 962 onCurrentLine(); 963 } 964 965 966 public void componentHidden(ComponentEvent e) { 967 } 968 969 970 public void componentMoved(ComponentEvent e) { 971 } 972 973 974 public void componentResized(ComponentEvent e) { 975 revalidate(); 976 } 977 978 979 public void componentShown(ComponentEvent e) { 980 } 981 982 private static class CvsAnnotation extends Annotation { 983 984 private final String text; 985 986 private Line line; 987 988 public CvsAnnotation(String tooltip, Line line) { 989 text = tooltip; 990 this.line = line; 991 } 992 993 public void attach() { 994 attach(line); 995 line = null; 996 } 997 998 public String getShortDescription() { 999 return text; 1000 } 1001 1002 public String getAnnotationType() { 1003 return "org-netbeans-modules-versioning-system-cvss-Annotation"; } 1005 } 1006} 1007 | Popular Tags |