1 19 20 package org.netbeans.editor; 21 22 import java.util.LinkedList ; 23 import java.util.HashMap ; 24 import org.netbeans.editor.BaseDocument; 25 import org.netbeans.editor.DrawLayerFactory; 26 import javax.swing.text.BadLocationException ; 27 import java.util.Iterator ; 28 import java.util.ArrayList ; 29 import javax.swing.event.DocumentListener ; 30 import org.netbeans.editor.BaseDocumentEvent; 31 import javax.swing.event.DocumentEvent ; 32 import javax.swing.event.EventListenerList ; 33 import java.util.EventListener ; 34 import java.beans.PropertyChangeListener ; 35 import java.beans.PropertyChangeEvent ; 36 import java.util.Comparator ; 37 import org.netbeans.editor.AnnotationDesc; 38 import org.netbeans.editor.AnnotationTypes; 39 import javax.swing.JPopupMenu ; 40 import javax.swing.Action ; 41 import java.util.Map ; 42 import java.util.TreeSet ; 43 import javax.swing.JMenu ; 44 import javax.swing.JMenuItem ; 45 import javax.swing.SwingUtilities ; 46 import org.netbeans.editor.ext.ExtKit; 47 import org.openide.util.NbBundle; 48 import org.openide.util.RequestProcessor; 49 import org.openide.util.actions.Presenter; 50 51 68 public class Annotations implements DocumentListener { 69 70 71 private HashMap lineAnnotationsByMark; 72 73 74 private ArrayList lineAnnotationsArray; 75 76 77 private DrawLayerFactory.AnnotationLayer drawLayer; 78 79 80 private BaseDocument doc; 81 82 83 private EventListenerList listenerList; 84 85 86 private PropertyChangeListener l; 87 88 89 private PropertyChangeListener annoTypesListener; 90 91 92 private boolean glyphColumn = false; 93 94 95 private boolean glyphButtonColumn = false; 96 97 98 private boolean menuInitialized = false; 99 100 101 public static final Comparator MENU_COMPARATOR = new MenuComparator(); 102 103 public Annotations(BaseDocument doc) { 104 lineAnnotationsByMark = new HashMap (30); 105 lineAnnotationsArray = new ArrayList (20); 106 listenerList = new EventListenerList (); 107 108 drawLayer = null; 109 this.doc = doc; 110 111 doc.addLayer(new DrawLayerFactory.AnnotationLayer(doc), 113 DrawLayerFactory.ANNOTATION_LAYER_VISIBILITY); 114 115 this.doc.addDocumentListener(this); 117 118 l = new PropertyChangeListener () { 119 public void propertyChange (PropertyChangeEvent evt) { 120 if (evt.getPropertyName() == AnnotationDesc.PROP_ANNOTATION_TYPE) { 121 AnnotationDesc anno = (AnnotationDesc)evt.getSource(); 122 LineAnnotations lineAnnos = (LineAnnotations)lineAnnotationsByMark.get(anno.getMark()); 123 lineAnnos.refreshAnnotations(); 124 refreshLine(lineAnnos.getLine()); 125 } 126 if (evt.getPropertyName() == AnnotationDesc.PROP_MOVE_TO_FRONT) { 127 AnnotationDesc anno = (AnnotationDesc)evt.getSource(); 128 frontAnnotation(anno); 129 } 130 } 131 }; 132 133 AnnotationTypes.getTypes().addPropertyChangeListener( annoTypesListener = new PropertyChangeListener () { 134 public void propertyChange (PropertyChangeEvent evt) { 135 if (evt.getPropertyName() == AnnotationTypes.PROP_COMBINE_GLYPHS) { 136 LineAnnotations lineAnnos; 137 for( Iterator it = lineAnnotationsArray.iterator(); it.hasNext(); ) { 138 lineAnnos = (LineAnnotations)it.next(); 139 lineAnnos.refreshAnnotations(); 140 } 141 } 142 if (evt.getPropertyName() == AnnotationTypes.PROP_ANNOTATION_TYPES) { 143 LineAnnotations lineAnnos; 144 for( Iterator it = lineAnnotationsArray.iterator(); it.hasNext(); ) { 145 lineAnnos = (LineAnnotations)it.next(); 146 for( Iterator it2 = lineAnnos.getAnnotations(); it2.hasNext(); ) { 147 AnnotationDesc anno = (AnnotationDesc)it2.next(); 148 anno.updateAnnotationType(); 149 } 150 } 151 } 152 fireChangedAll(); 153 } 154 }); 155 156 } 157 158 159 public synchronized DrawLayerFactory.AnnotationLayer getLayer() { 160 if (drawLayer == null) 161 drawLayer = (DrawLayerFactory.AnnotationLayer)doc.findLayer(DrawLayerFactory.ANNOTATION_LAYER_NAME); 162 return drawLayer; 163 } 164 165 166 public void addAnnotation(AnnotationDesc anno) { 167 168 if (!SwingUtilities.isEventDispatchThread()) { 170 throw new IllegalStateException ("Must be run in EQ"); } 172 173 MarkChain chain = getLayer().getMarkChain(); 175 try { 176 199 chain.addMark(anno.getOffset(), true); 200 201 } catch (BadLocationException e) { 202 213 throw new IllegalStateException ("offset=" + anno.getOffset() + ", docLen=" + doc.getLength()); } 216 MarkFactory.ChainDrawMark annoMark = chain.getAddedMark(); 218 if (annoMark == null) { 219 throw new NullPointerException (); 220 } 221 anno.setMark(annoMark); 222 223 229 LineAnnotations lineAnnos = (LineAnnotations)lineAnnotationsByMark.get(annoMark); 230 if (lineAnnos == null) { 231 lineAnnos = getLineAnnotations(anno.getLine()); 234 if (lineAnnos == null) { 235 lineAnnos = new LineAnnotations(); 236 lineAnnos.addAnnotation(anno); 237 if (lineAnnotationsByMark.put(anno.getMark(), lineAnnos) != null) { 238 throw new IllegalStateException ("Mark already in the map."); } 240 241 boolean inserted = false; 243 for (int i=0; i < lineAnnotationsArray.size(); i++) { 244 if (((LineAnnotations)lineAnnotationsArray.get(i)).getLine() > lineAnnos.getLine()) { 245 lineAnnotationsArray.add(i, lineAnnos); 246 inserted = true; 247 break; 248 } 249 } 250 if (!inserted) 251 lineAnnotationsArray.add(lineAnnos); 252 253 } 254 else { 255 lineAnnos.addAnnotation(anno); 256 if (lineAnnotationsByMark.get(anno.getMark()) == null) 260 lineAnnotationsByMark.put(anno.getMark(), lineAnnos); 261 } 262 263 } else { lineAnnos.addAnnotation(anno); 265 } 266 267 anno.addPropertyChangeListener(l); 269 270 if (anno.isVisible() && (!anno.isDefaultGlyph() || (anno.isDefaultGlyph() && lineAnnos.getCount() > 1))) { 272 glyphColumn = true; 273 } 274 275 if (lineAnnos.getCount() > 1) 276 glyphButtonColumn = true; 277 278 refreshLine(lineAnnos.getLine()); 280 281 } 283 284 285 public void removeAnnotation(AnnotationDesc anno) { 286 287 if (!SwingUtilities.isEventDispatchThread()) { 289 throw new IllegalStateException ("Must be run in EQ"); } 291 292 MarkFactory.ChainDrawMark annoMark = (MarkFactory.ChainDrawMark)anno.getMark(); 294 if (annoMark == null) { 295 throw new NullPointerException (); 296 } 297 298 LineAnnotations lineAnnos = (LineAnnotations)lineAnnotationsByMark.get(annoMark); 299 300 int line = lineAnnos.getLine(); 301 lineAnnos.removeAnnotation(anno); 303 304 if (!lineAnnos.isMarkStillReferenced(annoMark)) { 306 if (lineAnnotationsByMark.remove(annoMark) != lineAnnos) { 307 throw new IllegalStateException (); 308 } 309 310 MarkChain chain = getLayer().getMarkChain(); 311 if (!chain.removeMark(annoMark)) { 314 throw new IllegalStateException ("Mark not removed"); } 316 } 317 318 if (lineAnnos.getCount() == 0) { 320 int index = lineAnnotationsArray.indexOf(lineAnnos); 321 if (index != -1) { 324 lineAnnotationsArray.remove(index); 325 } 326 } 327 328 anno.setMark(null); 330 331 anno.removePropertyChangeListener(l); 333 334 refreshLine(line); 336 } 338 339 341 public AnnotationDesc getActiveAnnotation(Mark mark) { 342 LineAnnotations annos; 343 annos = (LineAnnotations)lineAnnotationsByMark.get(mark); 344 if (annos == null) { 345 return null; 346 } 347 AnnotationDesc anno = annos.getActive(); 348 if (anno==null || anno.getMark() != mark) { 351 return null; 352 } 353 return anno; 354 } 355 356 357 AnnotationDesc getLineActiveAnnotation(Mark mark) { 358 LineAnnotations annos; 359 annos = (LineAnnotations)lineAnnotationsByMark.get(mark); 360 if (annos == null) { 361 return null; 362 } 363 AnnotationDesc anno = annos.getActive(); 364 return anno; 365 } 366 367 368 protected LineAnnotations getLineAnnotations(int line) { 369 LineAnnotations annos; 370 int low = 0; 372 int high = lineAnnotationsArray.size() - 1; 373 while (low <= high) { 374 int mid = (low + high) / 2; 375 annos = (LineAnnotations)lineAnnotationsArray.get(mid); 376 int annosLine = annos.getLine(); 377 if (line < annosLine) { 378 high = mid - 1; 379 } else if (line > annosLine) { 380 low = mid + 1; 381 } else { 382 return annos; 383 } 384 } 385 return null; 386 } 387 388 390 public AnnotationDesc getActiveAnnotation(int line) { 391 LineAnnotations annos = getLineAnnotations(line); 392 if (annos == null) 393 return null; 394 return annos.getActive(); 395 } 396 397 399 public void frontAnnotation(AnnotationDesc anno) { 400 int line = anno.getLine(); 401 LineAnnotations annos = getLineAnnotations(line); 402 if (annos == null) 403 return; 404 annos.activate(anno); 405 refreshLine(line); 406 } 407 408 410 public AnnotationDesc activateNextAnnotation(int line) { 411 LineAnnotations annos = getLineAnnotations(line); 412 if (annos == null) 413 return null; 414 AnnotationDesc aa = annos.activateNext(); 415 refreshLine(line); 416 return aa; 417 } 418 419 420 public int getNextLineWithAnnotation(int line) { 421 LineAnnotations annos; 422 423 int low = 0; 425 int high = lineAnnotationsArray.size() - 1; 426 while (low <= high) { 427 int mid = (low + high) / 2; 428 annos = (LineAnnotations)lineAnnotationsArray.get(mid); 429 int annosLine = annos.getLine(); 430 if (line < annosLine) { 431 high = mid - 1; 432 } else if (line > annosLine) { 433 low = mid + 1; 434 } else { 435 return annosLine; 436 } 437 } 438 439 for (int i=low; i<lineAnnotationsArray.size(); i++) { 441 annos = (LineAnnotations)lineAnnotationsArray.get(i); 442 int annosLine = annos.getLine(); 443 if (annosLine >= line){ 444 return annosLine; 445 } 446 } 447 448 return -1; 449 } 450 451 452 public AnnotationDesc getAnnotation(int line, String type) { 453 return null; 454 } 455 456 457 public AnnotationDesc[] getPasiveAnnotations(int line) { 458 LineAnnotations annos = getLineAnnotations(line); 459 if (annos == null) 460 return null; 461 if (annos.getCount() <= 1) 462 return null; 463 return annos.getPasive(); 464 } 465 466 467 public AnnotationDesc[] getPassiveAnnotations(int offset){ 468 int lineIndex = doc.getDefaultRootElement().getElementIndex(offset); 469 return (lineIndex>=0) ? getPasiveAnnotations(lineIndex) : null; 470 } 471 472 473 public int getNumberOfAnnotations(int line) { 474 LineAnnotations annos = getLineAnnotations(line); 475 if (annos == null) 476 return 0; 477 return annos.getCount(); 478 } 479 480 481 482 protected void refreshLine(int line) { 483 fireChangedLine(line); 484 int start = Utilities.getRowStartFromLineOffset(doc, line); 485 int end = Utilities.getRowStartFromLineOffset(doc, line+1); 486 if (end == -1) 487 end = doc.getLength(); 488 doc.repaintBlock(start, end); 489 } 490 491 493 public void removeUpdate(DocumentEvent e) { 494 BaseDocumentEvent be = (BaseDocumentEvent)e; 495 int countOfDeletedLines = be.getLFCount(); 496 if (countOfDeletedLines == 0) 497 return; 498 499 int changedLine = be.getLine(); 500 501 511 fireChangedAll(); 513 } 514 515 517 public void insertUpdate(DocumentEvent e) { 518 BaseDocumentEvent be = (BaseDocumentEvent)e; 519 int countOfInsertedLines = be.getLFCount(); 520 if (countOfInsertedLines == 0) 521 return; 522 523 538 539 fireChangedAll(); 541 } 542 543 544 public void changedUpdate(DocumentEvent e) { 545 } 546 547 548 public void addAnnotationsListener(AnnotationsListener listener) { 549 listenerList.add(AnnotationsListener.class, listener); 550 } 551 552 553 public void removeAnnotationsListener(AnnotationsListener listener) { 554 listenerList.remove(AnnotationsListener.class, listener); 555 } 556 557 558 protected void fireChangedLine(int line) { 559 Object [] listeners = listenerList.getListenerList(); 561 for (int i = listeners.length-2; i>=0; i-=2) { 564 if (listeners[i]==AnnotationsListener.class) { 565 ((AnnotationsListener)listeners[i+1]).changedLine(line); 569 } 570 } 571 } 572 573 574 protected void fireChangedAll() { 575 Object [] listeners = listenerList.getListenerList(); 577 for (int i = listeners.length-2; i>=0; i-=2) { 580 if (listeners[i]==AnnotationsListener.class) { 581 ((AnnotationsListener)listeners[i+1]).changedAll(); 585 } 586 } 587 } 588 589 592 public boolean isGlyphColumn() { 593 return glyphColumn; 594 } 595 596 599 public boolean isGlyphButtonColumn() { 600 return glyphButtonColumn; 601 } 602 603 604 private void addAcceleretors(Action a, JMenuItem item, BaseKit kit){ 605 javax.swing.text.JTextComponent target = Utilities.getFocusedComponent(); 607 if (target == null) return; 608 javax.swing.text.Keymap km = target.getKeymap(); 609 if (km != null) { 610 javax.swing.KeyStroke [] keys = km.getKeyStrokesForAction(a); 611 if (keys != null && keys.length > 0) { 612 item.setAccelerator(keys[0]); 613 }else{ 614 String actionName = (String )a.getValue(Action.NAME); 616 if (actionName == null) return; 617 BaseAction action = (BaseAction)kit.getActionByName(actionName); 618 if (action == null) return; 619 keys = km.getKeyStrokesForAction(action); 620 if (keys != null && keys.length > 0) { 621 item.setAccelerator(keys[0]); 622 } 623 } 624 } 625 } 626 627 629 private JMenuItem createMenuItem(Action action, BaseKit kit) { 630 JMenuItem item; 631 if (action instanceof BaseAction) { 632 item = new JMenuItem ( ((BaseAction)action).getPopupMenuText(null) ); 633 item.addActionListener(action); 634 addAcceleretors(action, item, kit); 635 } else if (action instanceof Presenter.Popup) { 636 item = ((Presenter.Popup) action).getPopupPresenter(); 637 } else { 638 item = new JMenuItem ( (String )action.getValue(Action.NAME) ); 639 item.addActionListener(action); 640 addAcceleretors(action, item, kit); 641 } 642 return item; 643 } 644 645 646 public JPopupMenu createPopupMenu(BaseKit kit, int line) { 647 return createMenu(kit, line, false).getPopupMenu(); 648 } 649 650 private void initMenu(JMenu pm, BaseKit kit, int line){ 651 LineAnnotations annos = getLineAnnotations(line); 652 Map types = new HashMap (AnnotationTypes.getTypes().getVisibleAnnotationTypeNamesCount() * 4/3); 653 654 Action [] actions; 655 boolean separator = false; 656 boolean added = false; 657 JMenu subMenu; 658 TreeSet orderedSubMenus = new TreeSet (MENU_COMPARATOR); 659 660 if (annos != null) { 661 662 AnnotationDesc anno = annos.getActive(); 664 if (anno != null) { 665 actions = anno.getActions(); 666 if (actions != null) { 667 subMenu = new JMenu (anno.getAnnotationTypeInstance().getDescription()); 668 for (int j=0; j<actions.length; j++) 669 subMenu.add(createMenuItem(actions[j], kit)); 670 671 if (subMenu.getItemCount() > 0) { 672 orderedSubMenus.add(subMenu); 673 separator = true; 674 } 675 types.put(anno.getAnnotationType(), anno.getAnnotationType()); 676 } 677 } 678 679 AnnotationDesc[] pasiveAnnos = annos.getPasive(); 681 added = false; 682 if (pasiveAnnos != null) { 683 for (int i=0; i < pasiveAnnos.length; i++) { 684 actions = pasiveAnnos[i].getActions(); 685 if (actions != null) { 686 subMenu = new JMenu (pasiveAnnos[i].getAnnotationTypeInstance().getDescription()); 687 for (int j=0; j<actions.length; j++) 688 subMenu.add(createMenuItem(actions[j], kit)); 689 if (separator) { 690 separator = false; 691 } 693 if (subMenu.getItemCount() > 0){ 694 orderedSubMenus.add(subMenu); 696 added = true; 697 } 698 types.put(pasiveAnnos[i].getAnnotationType(), pasiveAnnos[i].getAnnotationType()); 699 } 700 } 701 if (added) 702 separator = true; 703 } 704 } 705 706 added = false; 708 AnnotationType type; 709 for (Iterator i = AnnotationTypes.getTypes().getAnnotationTypeNames(); i.hasNext(); ) { 710 type = AnnotationTypes.getTypes().getType((String )i.next()); 711 if (type == null || !type.isVisible()) 712 continue; 713 if (types.get(type.getName()) != null) 714 continue; 715 actions = type.getActions(); 716 if (actions != null) { 717 subMenu = new JMenu (type.getDescription()); 718 for (int j=0; j<actions.length; j++) { 719 if (actions[j].isEnabled()) { 720 subMenu.add(createMenuItem(actions[j], kit)); 721 } 722 } 723 if (separator) { 724 separator = false; 725 } 727 if (subMenu.getItemCount() > 0){ 728 orderedSubMenus.add(subMenu); 730 added = true; 731 } 732 } 733 } 734 735 if (added) 736 separator = true; 737 738 742 743 if (!orderedSubMenus.isEmpty()){ 744 Iterator iter = orderedSubMenus.iterator(); 745 while(iter.hasNext()){ 746 subMenu = (JMenu ) iter.next(); 747 pm.add(subMenu); 748 } 749 pm.addSeparator(); 750 } 751 752 753 BaseAction action = (BaseAction)kit.getActionByName(BaseKit.toggleLineNumbersAction); 755 pm.add(action.getPopupMenuItem(null)); 756 757 BaseAction action2 = (BaseAction)kit.getActionByName(ExtKit.toggleToolbarAction); 758 if (action2 != null){ 759 pm.add(action2.getPopupMenuItem(null)); 760 } 761 menuInitialized = true; 762 } 763 764 private static class DelayedMenu extends JMenu { 765 766 RequestProcessor.Task task; 767 768 public DelayedMenu(String s){ 769 super(s); 770 } 771 772 public JPopupMenu getPopupMenu() { 773 RequestProcessor.Task t = task; 774 if (t!=null && !t.isFinished()){ 775 t.waitFinished(); 776 } 777 return super.getPopupMenu(); 778 } 779 780 void setTask(RequestProcessor.Task task){ 781 this.task = task; 782 } 783 784 void clearTask() { 785 this.task = null; } 787 } 788 789 private JMenu createMenu(BaseKit kit, int line, boolean backgroundInit){ 790 final DelayedMenu pm = new DelayedMenu(NbBundle.getBundle(BaseKit.class).getString("generate-gutter-popup")); 791 final BaseKit fKit = kit; 792 final int fLine = line; 793 794 if (backgroundInit){ 795 RequestProcessor rp = RequestProcessor.getDefault(); 796 RequestProcessor.Task task = rp.create(new Runnable (){ 797 public void run(){ 798 initMenu(pm, fKit, fLine); 799 pm.clearTask(); } 801 }); 802 pm.setTask(task); task.schedule(0); 804 }else{ 805 initMenu(pm, fKit, fLine); 806 } 807 808 return pm; 809 } 810 811 812 public JMenu createMenu(BaseKit kit, int line) { 813 boolean bkgInit = menuInitialized; 814 menuInitialized = true; 815 return createMenu(kit, line, !bkgInit); 816 } 817 818 private String dumpAnnotaionDesc(AnnotationDesc ad) { 819 return "offset=" + ad.getOffset() + "(ls=" + doc.getParagraphElement(ad.getOffset()).getStartOffset() + "), line=" + ad.getLine() + ", type=" + ad.getAnnotationType(); } 824 825 private String dumpLineAnnotationsArray() { 826 StringBuffer sb = new StringBuffer (); 827 for (int i = 0; i < lineAnnotationsArray.size(); i++) { 828 LineAnnotations la = (LineAnnotations)lineAnnotationsArray.get(i); 829 LinkedList annos = la.annos; 830 sb.append("[" + i + "]: line=" + la.getLine() + ", anos:"); for (int j = 0; j < annos.size(); j++) { 833 sb.append("\n [" + j + "]: " + dumpAnnotaionDesc((AnnotationDesc)annos.get(j))); } 835 sb.append('\n'); 836 } 837 return sb.toString(); 838 } 839 840 841 845 static public class LineAnnotations extends Object { 846 847 848 private LinkedList annos; 849 850 851 private LinkedList annosVisible; 852 853 855 private AnnotationDesc active; 856 857 858 860 protected LineAnnotations() { 861 annos = new LinkedList (); 862 annosVisible = new LinkedList (); 863 } 865 866 867 public void addAnnotation(AnnotationDesc anno) { 868 annos.add(anno); 871 if (anno.isVisible()) { 872 active = anno; 873 } 874 refreshAnnotations(); 875 } 876 877 879 public void removeAnnotation(AnnotationDesc anno) { 880 if (anno == active) 881 activateNext(); 882 annos.remove(anno); 883 if (active == anno) 884 active = null; 885 refreshAnnotations(); 886 } 887 888 889 public AnnotationDesc getActive() { 890 return active; 891 } 892 893 894 public int getLine() { 895 return (annos.size() > 0) 897 ? ((AnnotationDesc)annos.get(0)).getLine() 898 : 0; 899 } 901 902 903 public void setLine(int line) { 904 throw new IllegalStateException ("Setting of line number not allowed"); } 907 908 909 public AnnotationDesc[] getPasive() { 910 AnnotationDesc[] pasives = new AnnotationDesc[getCount()-1]; 911 int startIndex = annosVisible.indexOf(getActive()); 912 int index = startIndex; 913 int i=0; 914 while (true) { 915 index++; 916 if (index >= annosVisible.size()) 917 index = 0; 918 if (index == startIndex) 919 break; 920 921 pasives[i] = (AnnotationDesc)annosVisible.get(index); 922 i++; 923 } 924 return pasives; 925 } 926 927 928 public boolean activate(AnnotationDesc anno) { 929 930 int i,j; 931 i = annosVisible.indexOf(anno); 932 933 if (i == -1) { 934 for(j=0; j < annosVisible.size(); j++) { 936 if (annosVisible.get(j) instanceof AnnotationCombination) { 937 if (((AnnotationCombination)annosVisible.get(j)).isAnnotationCombined(anno)) { 938 i = j; 939 anno = (AnnotationCombination)annosVisible.get(j); 940 break; 941 } 942 } 943 } 944 } 945 946 if (i == -1) 947 return false; 948 949 if (annosVisible.get(i) == null) 950 return false; 951 952 if (anno == active || !anno.isVisible()) 953 return false; 954 955 active = anno; 956 957 return true; 958 } 959 960 961 public int getCount() { 962 return annosVisible.size(); 963 } 964 965 966 public AnnotationDesc activateNext() { 967 if (getCount() <= 1) 968 return active; 969 970 int current = annosVisible.indexOf(active); 971 current++; 972 if (current >= getCount()) 973 current = 0; 974 active = (AnnotationDesc)annosVisible.get(current); 975 return active; 976 } 977 978 981 private void fillInCombinationsAndOrderThem(LinkedList combTypes) { 982 AnnotationType type; 983 AnnotationType.CombinationMember[] combs; 984 985 for (Iterator it = AnnotationTypes.getTypes().getAnnotationTypeNames(); it.hasNext(); ) { 986 type = AnnotationTypes.getTypes().getType((String )it.next()); 987 if (type == null) 988 continue; 989 combs = type.getCombinations(); 990 if (combs != null && type.isWholeLine() && 991 (combs.length >= 2 || (combs.length == 1 && combs[0].isAbsorbAll())) ) { 992 if (type.getCombinationOrder() == 0) { 993 combTypes.add(type); 994 } else { 995 boolean inserted = false; 996 for (int i=0; i < combTypes.size(); i++) { 997 if ( ((AnnotationType)combTypes.get(i)).getCombinationOrder() > type.getCombinationOrder()) { 998 combTypes.add(i, type); 999 inserted = true; 1000 break; 1001 } 1002 } 1003 if (!inserted) 1004 combTypes.add(type); 1005 } 1006 } 1007 } 1008 } 1009 1010 1015 private boolean combineType(AnnotationType combType, LinkedList annosDupl) { 1016 1017 int i, j, k; 1018 boolean matchedType; 1019 int countOfAnnos = 0; 1020 int valid_optional_count = 0; 1021 1022 LinkedList combinedAnnos = new LinkedList (); 1023 1024 AnnotationType.CombinationMember[] combs = combType.getCombinations(); 1025 1026 boolean matchedComb = true; 1028 AnnotationType.CombinationMember comb; 1029 AnnotationDesc anno; 1030 for (i=0; i < combs.length; i++) { 1031 1032 comb = combs[i]; 1033 matchedType = false; 1034 1035 for (j=0; j < annosDupl.size(); j++) { 1037 1038 anno = (AnnotationDesc)annosDupl.get(j); 1039 1040 if (anno == null) 1041 continue; 1042 1043 if (comb.getName().equals( anno.getAnnotationType() )) { 1045 countOfAnnos++; 1046 1047 if (comb.getMinimumCount() == 0) { 1049 matchedType = true; 1050 countOfAnnos++; 1051 combinedAnnos.add(anno); 1052 if (!comb.isAbsorbAll()) 1053 break; 1054 } else { 1055 int requiredCount = comb.getMinimumCount() - 1; 1056 for (k=j+1; (k < annosDupl.size()) && (requiredCount > 0); k++) { 1057 if (annosDupl.get(k) == null) 1058 continue; 1059 if (comb.getName().equals( ((AnnotationDesc)annosDupl.get(k)).getAnnotationType() )) { 1060 requiredCount--; 1061 } 1062 } 1063 if (requiredCount == 0) { 1064 matchedType = true; 1065 1066 combinedAnnos.add(anno); 1067 for (k=j+1; k < annosDupl.size(); k++) { 1068 if (annosDupl.get(k) == null) 1069 continue; 1070 if (comb.getName().equals( ((AnnotationDesc)annosDupl.get(k)).getAnnotationType() )) { 1071 countOfAnnos++; 1072 combinedAnnos.add(annosDupl.get(k)); 1073 } 1074 } 1075 } 1076 break; 1077 } 1078 1079 } 1080 1081 } 1082 1083 if (matchedType) { 1084 if (comb.isOptional()) 1085 valid_optional_count++; 1086 } else { 1087 if (!comb.isOptional()) { 1088 matchedComb = false; 1089 break; 1090 } 1091 } 1092 1093 } 1094 if (combType.getMinimumOptionals() > valid_optional_count) 1095 matchedComb = false; 1096 1097 AnnotationCombination annoComb = null; 1098 if (matchedComb) { 1099 1100 boolean activateComb = false; 1101 1102 for (i=0; i<combinedAnnos.size(); i++) { 1103 if (combinedAnnos.get(i) == active) 1104 activateComb = true; 1105 1106 if (annoComb == null) { 1107 annoComb = new AnnotationCombination(combType.getName(), (AnnotationDesc)combinedAnnos.get(i)); 1108 annosDupl.set(annosDupl.indexOf(combinedAnnos.get(i)),annoComb); } else { 1110 annoComb.addCombinedAnnotation((AnnotationDesc)combinedAnnos.get(i)); 1111 annosDupl.set(annosDupl.indexOf(combinedAnnos.get(i)),null); } 1113 } 1114 if (activateComb) 1115 active = annoComb; 1116 1117 return true; 1118 } 1119 1120 return false; 1121 } 1122 1123 1124 1125 1126 1129 public void refreshAnnotations() { 1130 int i; 1131 1132 if (!AnnotationTypes.getTypes().isCombineGlyphs().booleanValue()) { 1133 1134 annosVisible = new LinkedList (); 1136 for (i=0; i < annos.size(); i++) { 1137 if ( ! ((AnnotationDesc)annos.get(i)).isVisible() ) 1138 continue; 1139 annosVisible.add(annos.get(i)); 1140 } 1141 1142 } else { 1143 1144 LinkedList annosDupl = (LinkedList )annos.clone(); 1146 1147 LinkedList combTypes = new LinkedList (); 1149 1150 fillInCombinationsAndOrderThem(combTypes); 1152 1153 for (int ct=0; ct < combTypes.size(); ct++) { 1154 combineType((AnnotationType)combTypes.get(ct), annosDupl); 1155 } 1156 1157 annosVisible = new LinkedList (); 1158 1159 for (i=0; i < annosDupl.size(); i++) { 1161 if (annosDupl.get(i) != null && ((AnnotationDesc)annosDupl.get(i)).isVisible() ) 1162 annosVisible.add(annosDupl.get(i)); 1163 } 1164 } 1165 1166 if (annosVisible.indexOf(active) == -1) { 1168 if (annosVisible.size() > 0) 1169 active = (AnnotationDesc)annosVisible.get(0); 1170 else 1171 active = null; 1172 } 1173 } 1174 1175 1177 public boolean isMarkStillReferenced(Mark mark) { 1178 AnnotationDesc anno; 1179 for( Iterator it = annos.listIterator(); it.hasNext(); ) { 1180 anno = (AnnotationDesc)it.next(); 1181 if (anno.getMark() == mark) 1182 return true; 1183 } 1184 return false; 1185 } 1186 1187 public Iterator getAnnotations() { 1188 return annos.iterator(); 1189 } 1190 1191 } 1192 1193 1194 1195 public interface AnnotationsListener extends EventListener { 1196 1197 1199 public void changedLine(int Line); 1200 1201 1204 public void changedAll(); 1205 1206 } 1207 1208 1213 private static class AnnotationCombination extends AnnotationDesc { 1214 1215 1216 private AnnotationDesc delegate; 1217 1218 1219 private String type; 1220 1221 1222 private LinkedList list; 1223 1224 public AnnotationCombination(String type, AnnotationDesc delegate) { 1225 super(delegate.getOffset(), delegate.getLength()); 1226 this.delegate = delegate; 1227 this.type = type; 1228 updateAnnotationType(); 1229 list = new LinkedList (); 1230 list.add(delegate); 1231 } 1232 1233 1234 public int getOffset() { 1235 return delegate.getOffset(); 1236 } 1237 1238 1239 public int getLine() { 1240 return delegate.getLine(); 1241 } 1242 1243 1244 public String getShortDescription() { 1245 return getAnnotationTypeInstance().getDescription(); 1246 } 1247 1248 1249 public String getAnnotationType() { 1250 return type; 1251 } 1252 1253 1254 public void addCombinedAnnotation(AnnotationDesc anno) { 1255 list.add(anno); 1256 } 1257 1258 1259 public boolean isAnnotationCombined(AnnotationDesc anno) { 1260 if (list.indexOf(anno) == -1) 1261 return false; 1262 else 1263 return true; 1264 } 1265 1266 1267 Mark getMark() { 1268 return delegate.getMark(); 1269 } 1270 1271 } 1272 1273 public static final class MenuComparator implements Comparator { 1274 1275 1276 public MenuComparator() { 1277 } 1278 1279 public int compare(Object o1, Object o2) { 1280 JMenu menuOne = (JMenu )o1; 1281 JMenu menuTwo = (JMenu )o2; 1282 if (menuTwo == null || menuOne == null) return 0; 1283 String menuOneText = menuOne.getText(); 1284 String menuTwoText = menuTwo.getText(); 1285 if (menuTwoText == null || menuOneText == null) return 0; 1286 return menuOneText.compareTo(menuTwoText); 1287 } 1288 1289 } 1290 1291} 1292 | Popular Tags |