1 11 package org.eclipse.jface.text.source; 12 13 14 import java.util.ArrayList ; 15 import java.util.EventListener ; 16 import java.util.HashSet ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Set ; 20 21 import org.eclipse.swt.SWT; 22 import org.eclipse.swt.custom.StyledText; 23 import org.eclipse.swt.events.ControlListener; 24 import org.eclipse.swt.events.DisposeEvent; 25 import org.eclipse.swt.events.DisposeListener; 26 import org.eclipse.swt.events.FocusListener; 27 import org.eclipse.swt.events.HelpListener; 28 import org.eclipse.swt.events.KeyListener; 29 import org.eclipse.swt.events.MouseListener; 30 import org.eclipse.swt.events.MouseMoveListener; 31 import org.eclipse.swt.events.MouseTrackListener; 32 import org.eclipse.swt.events.PaintListener; 33 import org.eclipse.swt.events.TraverseListener; 34 import org.eclipse.swt.graphics.Font; 35 import org.eclipse.swt.graphics.Point; 36 import org.eclipse.swt.graphics.Rectangle; 37 import org.eclipse.swt.widgets.Canvas; 38 import org.eclipse.swt.widgets.Composite; 39 import org.eclipse.swt.widgets.Control; 40 import org.eclipse.swt.widgets.Display; 41 import org.eclipse.swt.widgets.Event; 42 import org.eclipse.swt.widgets.Layout; 43 import org.eclipse.swt.widgets.Listener; 44 import org.eclipse.swt.widgets.Menu; 45 46 import org.eclipse.core.runtime.Assert; 47 48 import org.eclipse.jface.text.BadLocationException; 49 import org.eclipse.jface.text.IDocument; 50 import org.eclipse.jface.text.IRegion; 51 import org.eclipse.jface.text.ITextViewer; 52 import org.eclipse.jface.text.ITextViewerExtension; 53 import org.eclipse.jface.text.ITextViewerExtension5; 54 55 56 71 public class CompositeRuler implements IVerticalRuler, IVerticalRulerExtension, IVerticalRulerInfoExtension { 72 73 74 77 class RulerLayout extends Layout { 78 79 82 protected RulerLayout() { 83 } 84 85 88 protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) { 89 Control[] children= composite.getChildren(); 90 Point size= new Point(0, 0); 91 for (int i= 0; i < children.length; i++) { 92 Point s= children[i].computeSize(SWT.DEFAULT, SWT.DEFAULT, flushCache); 93 size.x += s.x; 94 size.y= Math.max(size.y, s.y); 95 } 96 size.x += (Math.max(0, children.length -1) * fGap); 97 return size; 98 } 99 100 103 protected void layout(Composite composite, boolean flushCache) { 104 Rectangle clArea= composite.getClientArea(); 105 int rulerHeight= clArea.height; 106 107 int x= 0; 108 Iterator e= fDecorators.iterator(); 109 while (e.hasNext()) { 110 IVerticalRulerColumn column= (IVerticalRulerColumn) e.next(); 111 int columnWidth= column.getWidth(); 112 column.getControl().setBounds(x, 0, columnWidth, rulerHeight); 113 x += (columnWidth + fGap); 114 } 115 } 116 } 117 118 122 static class CompositeRulerCanvas extends Canvas { 123 124 127 static class ListenerInfo { 128 Class fClass; 129 EventListener fListener; 130 } 131 132 133 private List fCachedListeners= new ArrayList (); 134 138 private Listener fMenuDetectListener; 139 140 146 public CompositeRulerCanvas(Composite parent, int style) { 147 super(parent, style); 148 fMenuDetectListener= new Listener () { 149 public void handleEvent(Event event) { 150 if (event.type == SWT.MenuDetect) { 151 Menu menu= getMenu(); 152 if (menu != null) { 153 menu.setLocation(event.x, event.y); 154 menu.setVisible(true); 155 } 156 } 157 } 158 }; 159 super.addDisposeListener(new DisposeListener() { 160 public void widgetDisposed(DisposeEvent e) { 161 if (fCachedListeners != null) { 162 fCachedListeners.clear(); 163 fCachedListeners= null; 164 } 165 } 166 }); 167 } 168 169 177 private void addListener(Class clazz, Control control, EventListener listener) { 178 if (ControlListener.class.equals(clazz)) { 179 control. addControlListener((ControlListener) listener); 180 return; 181 } 182 if (FocusListener.class.equals(clazz)) { 183 control. addFocusListener((FocusListener) listener); 184 return; 185 } 186 if (HelpListener.class.equals(clazz)) { 187 control. addHelpListener((HelpListener) listener); 188 return; 189 } 190 if (KeyListener.class.equals(clazz)) { 191 control. addKeyListener((KeyListener) listener); 192 return; 193 } 194 if (MouseListener.class.equals(clazz)) { 195 control. addMouseListener((MouseListener) listener); 196 return; 197 } 198 if (MouseMoveListener.class.equals(clazz)) { 199 control. addMouseMoveListener((MouseMoveListener) listener); 200 return; 201 } 202 if (MouseTrackListener.class.equals(clazz)) { 203 control. addMouseTrackListener((MouseTrackListener) listener); 204 return; 205 } 206 if (PaintListener.class.equals(clazz)) { 207 control. addPaintListener((PaintListener) listener); 208 return; 209 } 210 if (TraverseListener.class.equals(clazz)) { 211 control. addTraverseListener((TraverseListener) listener); 212 return; 213 } 214 if (DisposeListener.class.equals(clazz)) { 215 control. addDisposeListener((DisposeListener) listener); 216 return; 217 } 218 } 219 220 228 private void removeListener(Class clazz, Control control, EventListener listener) { 229 if (ControlListener.class.equals(clazz)) { 230 control. removeControlListener((ControlListener) listener); 231 return; 232 } 233 if (FocusListener.class.equals(clazz)) { 234 control. removeFocusListener((FocusListener) listener); 235 return; 236 } 237 if (HelpListener.class.equals(clazz)) { 238 control. removeHelpListener((HelpListener) listener); 239 return; 240 } 241 if (KeyListener.class.equals(clazz)) { 242 control. removeKeyListener((KeyListener) listener); 243 return; 244 } 245 if (MouseListener.class.equals(clazz)) { 246 control. removeMouseListener((MouseListener) listener); 247 return; 248 } 249 if (MouseMoveListener.class.equals(clazz)) { 250 control. removeMouseMoveListener((MouseMoveListener) listener); 251 return; 252 } 253 if (MouseTrackListener.class.equals(clazz)) { 254 control. removeMouseTrackListener((MouseTrackListener) listener); 255 return; 256 } 257 if (PaintListener.class.equals(clazz)) { 258 control. removePaintListener((PaintListener) listener); 259 return; 260 } 261 if (TraverseListener.class.equals(clazz)) { 262 control. removeTraverseListener((TraverseListener) listener); 263 return; 264 } 265 if (DisposeListener.class.equals(clazz)) { 266 control. removeDisposeListener((DisposeListener) listener); 267 return; 268 } 269 } 270 271 278 private void addListener(Class clazz, EventListener listener) { 279 Control[] children= getChildren(); 280 for (int i= 0; i < children.length; i++) { 281 if (children[i] != null && !children[i].isDisposed()) 282 addListener(clazz, children[i], listener); 283 } 284 285 ListenerInfo info= new ListenerInfo(); 286 info.fClass= clazz; 287 info.fListener= listener; 288 fCachedListeners.add(info); 289 } 290 291 298 private void removeListener(Class clazz, EventListener listener) { 299 int length= fCachedListeners.size(); 300 for (int i= 0; i < length; i++) { 301 ListenerInfo info= (ListenerInfo) fCachedListeners.get(i); 302 if (listener == info.fListener && clazz.equals(info.fClass)) { 303 fCachedListeners.remove(i); 304 break; 305 } 306 } 307 308 Control[] children= getChildren(); 309 for (int i= 0; i < children.length; i++) { 310 if (children[i] != null && !children[i].isDisposed()) 311 removeListener(clazz, children[i], listener); 312 } 313 } 314 315 320 public void childAdded(Control child) { 321 if (child != null && !child.isDisposed()) { 322 int length= fCachedListeners.size(); 323 for (int i= 0; i < length; i++) { 324 ListenerInfo info= (ListenerInfo) fCachedListeners.get(i); 325 addListener(info.fClass, child, info.fListener); 326 } 327 child.addListener(SWT.MenuDetect, fMenuDetectListener); 328 } 329 } 330 331 336 public void childRemoved(Control child) { 337 if (child != null && !child.isDisposed()) { 338 int length= fCachedListeners.size(); 339 for (int i= 0; i < length; i++) { 340 ListenerInfo info= (ListenerInfo) fCachedListeners.get(i); 341 removeListener(info.fClass, child, info.fListener); 342 } 343 child.removeListener(SWT.MenuDetect, fMenuDetectListener); 344 } 345 } 346 347 350 public void removeControlListener(ControlListener listener) { 351 removeListener(ControlListener.class, listener); 352 super.removeControlListener(listener); 353 } 354 355 358 public void removeFocusListener(FocusListener listener) { 359 removeListener(FocusListener.class, listener); 360 super.removeFocusListener(listener); 361 } 362 363 366 public void removeHelpListener(HelpListener listener) { 367 removeListener(HelpListener.class, listener); 368 super.removeHelpListener(listener); 369 } 370 371 374 public void removeKeyListener(KeyListener listener) { 375 removeListener(KeyListener.class, listener); 376 super.removeKeyListener(listener); 377 } 378 379 382 public void removeMouseListener(MouseListener listener) { 383 removeListener(MouseListener.class, listener); 384 super.removeMouseListener(listener); 385 } 386 387 390 public void removeMouseMoveListener(MouseMoveListener listener) { 391 removeListener(MouseMoveListener.class, listener); 392 super.removeMouseMoveListener(listener); 393 } 394 395 398 public void removeMouseTrackListener(MouseTrackListener listener) { 399 removeListener(MouseTrackListener.class, listener); 400 super.removeMouseTrackListener(listener); 401 } 402 403 406 public void removePaintListener(PaintListener listener) { 407 removeListener(PaintListener.class, listener); 408 super.removePaintListener(listener); 409 } 410 411 414 public void removeTraverseListener(TraverseListener listener) { 415 removeListener(TraverseListener.class, listener); 416 super.removeTraverseListener(listener); 417 } 418 419 422 public void removeDisposeListener(DisposeListener listener) { 423 removeListener(DisposeListener.class, listener); 424 super.removeDisposeListener(listener); 425 } 426 427 430 public void addControlListener(ControlListener listener) { 431 super.addControlListener(listener); 432 addListener(ControlListener.class, listener); 433 } 434 435 438 public void addFocusListener(FocusListener listener) { 439 super.addFocusListener(listener); 440 addListener(FocusListener.class, listener); 441 } 442 443 446 public void addHelpListener(HelpListener listener) { 447 super.addHelpListener(listener); 448 addListener(HelpListener.class, listener); 449 } 450 451 454 public void addKeyListener(KeyListener listener) { 455 super.addKeyListener(listener); 456 addListener(KeyListener.class, listener); 457 } 458 459 462 public void addMouseListener(MouseListener listener) { 463 super.addMouseListener(listener); 464 addListener(MouseListener.class, listener); 465 } 466 467 470 public void addMouseMoveListener(MouseMoveListener listener) { 471 super.addMouseMoveListener(listener); 472 addListener(MouseMoveListener.class, listener); 473 } 474 475 478 public void addMouseTrackListener(MouseTrackListener listener) { 479 super.addMouseTrackListener(listener); 480 addListener(MouseTrackListener.class, listener); 481 } 482 483 486 public void addPaintListener(PaintListener listener) { 487 super.addPaintListener(listener); 488 addListener(PaintListener.class, listener); 489 } 490 491 494 public void addTraverseListener(TraverseListener listener) { 495 super.addTraverseListener(listener); 496 addListener(TraverseListener.class, listener); 497 } 498 499 502 public void addDisposeListener(DisposeListener listener) { 503 super.addDisposeListener(listener); 504 addListener(DisposeListener.class, listener); 505 } 506 } 507 508 509 private ITextViewer fTextViewer; 510 511 private CompositeRulerCanvas fComposite; 512 513 private IAnnotationModel fModel; 514 515 private List fDecorators= new ArrayList (2); 516 517 private Point fLocation= new Point(-1, -1); 518 519 private int fLastMouseButtonActivityLine= -1; 520 521 private int fGap; 522 526 private Set fAnnotationListeners= new HashSet (); 527 528 529 532 public CompositeRuler() { 533 this(0); 534 } 535 536 541 public CompositeRuler(int gap) { 542 fGap= gap; 543 } 544 545 552 public void addDecorator(int index, IVerticalRulerColumn rulerColumn) { 553 rulerColumn.setModel(getModel()); 554 555 if (index > fDecorators.size()) 556 fDecorators.add(rulerColumn); 557 else 558 fDecorators.add(index, rulerColumn); 559 560 if (fComposite != null && !fComposite.isDisposed()) { 561 rulerColumn.createControl(this, fComposite); 562 fComposite.childAdded(rulerColumn.getControl()); 563 layoutTextViewer(); 564 } 565 } 566 567 572 public void removeDecorator(int index) { 573 IVerticalRulerColumn rulerColumn= (IVerticalRulerColumn) fDecorators.get(index); 574 removeDecorator(rulerColumn); 575 } 576 577 583 public void removeDecorator(IVerticalRulerColumn rulerColumn) { 584 fDecorators.remove(rulerColumn); 585 if (rulerColumn != null) { 586 Control cc= rulerColumn.getControl(); 587 if (cc != null && !cc.isDisposed()) { 588 fComposite.childRemoved(cc); 589 cc.dispose(); 590 } 591 } 592 layoutTextViewer(); 593 } 594 595 599 private void layoutTextViewer() { 600 601 Control parent= fTextViewer.getTextWidget(); 602 603 if (fTextViewer instanceof ITextViewerExtension) { 604 ITextViewerExtension extension= (ITextViewerExtension) fTextViewer; 605 parent= extension.getControl(); 606 } 607 608 if (parent instanceof Composite && !parent.isDisposed()) 609 ((Composite) parent).layout(true); 610 } 611 612 615 public Control getControl() { 616 return fComposite; 617 } 618 619 622 public Control createControl(Composite parent, ITextViewer textViewer) { 623 624 fTextViewer= textViewer; 625 626 fComposite= new CompositeRulerCanvas(parent, SWT.NONE); 627 fComposite.setLayout(new RulerLayout()); 628 629 Iterator iter= fDecorators.iterator(); 630 while (iter.hasNext()) { 631 IVerticalRulerColumn column= (IVerticalRulerColumn) iter.next(); 632 column.createControl(this, fComposite); 633 fComposite.childAdded(column.getControl()); 634 } 635 636 return fComposite; 637 } 638 639 642 public void setModel(IAnnotationModel model) { 643 644 fModel= model; 645 646 Iterator e= fDecorators.iterator(); 647 while (e.hasNext()) { 648 IVerticalRulerColumn column= (IVerticalRulerColumn) e.next(); 649 column.setModel(model); 650 } 651 } 652 653 656 public IAnnotationModel getModel() { 657 return fModel; 658 } 659 660 663 public void update() { 664 if (fComposite != null && !fComposite.isDisposed()) { 665 Display d= fComposite.getDisplay(); 666 if (d != null) { 667 d.asyncExec(new Runnable () { 668 public void run() { 669 immediateUpdate(); 670 } 671 }); 672 } 673 } 674 } 675 676 681 public void immediateUpdate() { 682 Iterator e= fDecorators.iterator(); 683 while (e.hasNext()) { 684 IVerticalRulerColumn column= (IVerticalRulerColumn) e.next(); 685 column.redraw(); 686 } 687 } 688 689 692 public void setFont(Font font) { 693 Iterator e= fDecorators.iterator(); 694 while (e.hasNext()) { 695 IVerticalRulerColumn column= (IVerticalRulerColumn) e.next(); 696 column.setFont(font); 697 } 698 } 699 700 703 public int getWidth() { 704 int width= 0; 705 Iterator e= fDecorators.iterator(); 706 while (e.hasNext()) { 707 IVerticalRulerColumn column= (IVerticalRulerColumn) e.next(); 708 width += (column.getWidth() + fGap); 709 } 710 return Math.max(0, width - fGap); 711 } 712 713 716 public int getLineOfLastMouseButtonActivity() { 717 if (fLastMouseButtonActivityLine == -1) 718 fLastMouseButtonActivityLine= toDocumentLineNumber(fLocation.y); 719 return fLastMouseButtonActivityLine; 720 } 721 722 725 public int toDocumentLineNumber(int y_coordinate) { 726 if (fTextViewer == null || y_coordinate == -1) 727 return -1; 728 729 StyledText text= fTextViewer.getTextWidget(); 730 int line= text.getLineIndex(y_coordinate); 731 732 if (line == text.getLineCount() - 1) { 733 if (y_coordinate > text.getLinePixel(line + 1)) 735 return -1; 736 } 737 738 return widgetLine2ModelLine(fTextViewer, line); 739 } 740 741 750 protected final static int widgetLine2ModelLine(ITextViewer viewer, int widgetLine) { 751 752 if (viewer instanceof ITextViewerExtension5) { 753 ITextViewerExtension5 extension= (ITextViewerExtension5) viewer; 754 return extension.widgetLine2ModelLine(widgetLine); 755 } 756 757 try { 758 IRegion r= viewer.getVisibleRegion(); 759 IDocument d= viewer.getDocument(); 760 return widgetLine += d.getLineOfOffset(r.getOffset()); 761 } catch (BadLocationException x) { 762 } 763 return widgetLine; 764 } 765 766 771 public ITextViewer getTextViewer() { 772 return fTextViewer; 773 } 774 775 778 public void setLocationOfLastMouseButtonActivity(int x, int y) { 779 fLocation.x= x; 780 fLocation.y= y; 781 fLastMouseButtonActivityLine= -1; 782 } 783 784 791 public Iterator getDecoratorIterator() { 792 Assert.isNotNull(fDecorators, "fDecorators must be initialized"); return fDecorators.iterator(); 794 } 795 796 800 public IAnnotationHover getHover() { 801 return null; 802 } 803 804 808 public void addVerticalRulerListener(IVerticalRulerListener listener) { 809 fAnnotationListeners.add(listener); 810 } 811 812 816 public void removeVerticalRulerListener(IVerticalRulerListener listener) { 817 fAnnotationListeners.remove(listener); 818 } 819 820 828 public void fireAnnotationSelected(VerticalRulerEvent event) { 829 for (Iterator it= fAnnotationListeners.iterator(); it.hasNext();) { 831 IVerticalRulerListener listener= (IVerticalRulerListener) it.next(); 832 listener.annotationSelected(event); 833 } 834 } 835 836 844 public void fireAnnotationDefaultSelected(VerticalRulerEvent event) { 845 for (Iterator it= fAnnotationListeners.iterator(); it.hasNext();) { 847 IVerticalRulerListener listener= (IVerticalRulerListener) it.next(); 848 listener.annotationDefaultSelected(event); 849 } 850 } 851 852 861 public void fireAnnotationContextMenuAboutToShow(VerticalRulerEvent event, Menu menu) { 862 for (Iterator it= fAnnotationListeners.iterator(); it.hasNext();) { 864 IVerticalRulerListener listener= (IVerticalRulerListener) it.next(); 865 listener.annotationContextMenuAboutToShow(event, menu); 866 } 867 } 868 869 874 public void relayout() { 875 layoutTextViewer(); 876 } 877 } 878 | Popular Tags |