1 11 12 package org.eclipse.jface.text.source; 13 14 15 import java.util.Iterator ; 16 17 import org.eclipse.swt.SWT; 18 import org.eclipse.swt.custom.StyledText; 19 import org.eclipse.swt.events.ControlEvent; 20 import org.eclipse.swt.events.ControlListener; 21 import org.eclipse.swt.events.DisposeEvent; 22 import org.eclipse.swt.events.DisposeListener; 23 import org.eclipse.swt.events.KeyEvent; 24 import org.eclipse.swt.events.KeyListener; 25 import org.eclipse.swt.events.MouseEvent; 26 import org.eclipse.swt.events.MouseListener; 27 import org.eclipse.swt.events.MouseMoveListener; 28 import org.eclipse.swt.events.MouseTrackAdapter; 29 import org.eclipse.swt.events.ShellEvent; 30 import org.eclipse.swt.events.ShellListener; 31 import org.eclipse.swt.graphics.Point; 32 import org.eclipse.swt.graphics.Rectangle; 33 import org.eclipse.swt.widgets.Control; 34 import org.eclipse.swt.widgets.Display; 35 import org.eclipse.swt.widgets.Event; 36 import org.eclipse.swt.widgets.Listener; 37 38 import org.eclipse.core.runtime.Assert; 39 40 import org.eclipse.jface.text.AbstractHoverInformationControlManager; 41 import org.eclipse.jface.text.AbstractInformationControlManager; 42 import org.eclipse.jface.text.BadLocationException; 43 import org.eclipse.jface.text.IDocument; 44 import org.eclipse.jface.text.IInformationControl; 45 import org.eclipse.jface.text.IInformationControlCreator; 46 import org.eclipse.jface.text.IRegion; 47 import org.eclipse.jface.text.ITextViewerExtension5; 48 import org.eclipse.jface.text.JFaceTextUtil; 49 import org.eclipse.jface.text.Region; 50 import org.eclipse.jface.text.TextUtilities; 51 52 53 59 public class AnnotationBarHoverManager extends AbstractHoverInformationControlManager { 60 61 68 protected class Closer extends MouseTrackAdapter implements IInformationControlCloser, MouseListener, MouseMoveListener, ControlListener, KeyListener, DisposeListener, ShellListener, Listener { 69 70 71 private Control fSubjectControl; 72 73 private Rectangle fSubjectArea; 74 75 private boolean fIsActive= false; 76 77 private IInformationControl fInformationControlToClose; 78 82 private boolean fHasWheelFilter= false; 83 87 private Display fDisplay; 88 89 90 93 public Closer() { 94 } 95 96 99 public void setSubjectControl(Control control) { 100 fSubjectControl= control; 101 } 102 103 106 public void setInformationControl(IInformationControl control) { 107 fInformationControlToClose= control; 108 } 109 110 113 public void start(Rectangle subjectArea) { 114 115 if (fIsActive) return; 116 fIsActive= true; 117 118 fSubjectArea= subjectArea; 119 120 fInformationControlToClose.addDisposeListener(this); 121 if (fSubjectControl != null && !fSubjectControl.isDisposed()) { 122 fSubjectControl.addMouseListener(this); 123 fSubjectControl.addMouseMoveListener(this); 124 fSubjectControl.addMouseTrackListener(this); 125 fSubjectControl.getShell().addShellListener(this); 126 fSubjectControl.addControlListener(this); 127 fSubjectControl.addKeyListener(this); 128 129 fDisplay= fSubjectControl.getDisplay(); 130 if (!fDisplay.isDisposed() && fHideOnMouseWheel) { 131 fHasWheelFilter= true; 132 fDisplay.addFilter(SWT.MouseWheel, this); 133 } 134 } 135 } 136 137 140 public void stop() { 141 stop(false); 142 } 143 144 150 protected void stop(boolean delayRestart) { 151 152 if (!fIsActive) 153 return; 154 fIsActive= false; 155 156 hideInformationControl(); 157 158 if (fSubjectControl != null && !fSubjectControl.isDisposed()) { 159 fSubjectControl.removeMouseListener(this); 160 fSubjectControl.removeMouseMoveListener(this); 161 fSubjectControl.removeMouseTrackListener(this); 162 fSubjectControl.getShell().removeShellListener(this); 163 fSubjectControl.removeControlListener(this); 164 fSubjectControl.removeKeyListener(this); 165 } 166 167 if (fDisplay != null && !fDisplay.isDisposed() && fHasWheelFilter) 168 fDisplay.removeFilter(SWT.MouseWheel, this); 169 fHasWheelFilter= false; 170 171 fDisplay= null; 172 173 } 174 175 178 public void mouseMove(MouseEvent event) { 179 if (!fSubjectArea.contains(event.x, event.y)) 180 stop(); 181 } 182 183 186 public void mouseUp(MouseEvent event) { 187 } 188 189 192 public void mouseDown(MouseEvent event) { 193 stop(); 194 } 195 196 199 public void mouseDoubleClick(MouseEvent event) { 200 stop(); 201 } 202 203 207 public void handleEvent(Event event) { 208 if (event.type == SWT.MouseWheel) 209 stop(); 210 } 211 212 215 public void mouseExit(MouseEvent event) { 216 if (!fAllowMouseExit) 217 stop(); 218 } 219 220 223 public void controlResized(ControlEvent event) { 224 stop(); 225 } 226 227 230 public void controlMoved(ControlEvent event) { 231 stop(); 232 } 233 234 237 public void keyReleased(KeyEvent event) { 238 } 239 240 243 public void keyPressed(KeyEvent event) { 244 stop(true); 245 } 246 247 251 public void shellActivated(ShellEvent e) { 252 } 253 254 258 public void shellClosed(ShellEvent e) { 259 } 260 261 265 public void shellDeactivated(ShellEvent e) { 266 stop(); 267 } 268 269 273 public void shellDeiconified(ShellEvent e) { 274 } 275 276 280 public void shellIconified(ShellEvent e) { 281 } 282 283 286 public void widgetDisposed(DisposeEvent e) { 287 stop(); 288 } 289 } 290 291 292 private ISourceViewer fSourceViewer; 293 294 private IVerticalRulerInfo fVerticalRulerInfo; 295 296 private IAnnotationHover fAnnotationHover; 297 301 protected boolean fAllowMouseExit= false; 302 307 private boolean fHideOnMouseWheel= true; 308 309 313 private IAnnotationHover fCurrentHover; 314 315 325 public AnnotationBarHoverManager(ISourceViewer sourceViewer, IVerticalRuler ruler, IAnnotationHover annotationHover, IInformationControlCreator creator) { 326 this(ruler, sourceViewer, annotationHover, creator); 327 } 328 329 339 public AnnotationBarHoverManager(IVerticalRulerInfo rulerInfo, ISourceViewer sourceViewer, IAnnotationHover annotationHover, IInformationControlCreator creator) { 340 super(creator); 341 342 Assert.isNotNull(sourceViewer); 343 344 fSourceViewer= sourceViewer; 345 fVerticalRulerInfo= rulerInfo; 346 fAnnotationHover= annotationHover; 347 348 setAnchor(ANCHOR_RIGHT); 349 setMargins(5, 0); 350 setCloser(new Closer()); 351 } 352 353 356 protected void computeInformation() { 357 fAllowMouseExit= false; 358 MouseEvent event= getHoverEvent(); 359 IAnnotationHover hover= getHover(event); 360 if (hover == null) { 361 setInformation(null, null); 362 return; 363 } 364 365 int line= getHoverLine(event); 366 367 if (hover instanceof IAnnotationHoverExtension) { 368 IAnnotationHoverExtension extension= (IAnnotationHoverExtension) hover; 369 ILineRange range= extension.getHoverLineRange(fSourceViewer, line); 370 setCustomInformationControlCreator(extension.getHoverControlCreator()); 371 range= adaptLineRange(range, line); 372 if (range != null) 373 setInformation(extension.getHoverInfo(fSourceViewer, range, computeNumberOfVisibleLines()), computeArea(range)); 374 else 375 setInformation(null, null); 376 377 } else { 378 setCustomInformationControlCreator(null); 379 setInformation(hover.getHoverInfo(fSourceViewer, line), computeArea(line)); 380 } 381 382 } 383 384 388 protected void showInformationControl(Rectangle subjectArea) { 389 super.showInformationControl(subjectArea); 390 fCurrentHover= getHover(getHoverEvent()); 391 } 392 393 397 protected void hideInformationControl() { 398 fCurrentHover= null; 399 super.hideInformationControl(); 400 } 401 402 412 private ILineRange adaptLineRange(ILineRange lineRange, int line) { 413 if (lineRange != null) { 414 lineRange= adaptLineRangeToFolding(lineRange, line); 415 if (lineRange != null) 416 return adaptLineRangeToViewport(lineRange); 417 } 418 return null; 419 } 420 421 430 private ILineRange adaptLineRangeToFolding(ILineRange lineRange, int line) { 431 432 if (fSourceViewer instanceof ITextViewerExtension5) { 433 ITextViewerExtension5 extension= (ITextViewerExtension5) fSourceViewer; 434 435 try { 436 IRegion region= convertToRegion(lineRange); 437 IRegion[] coverage= extension.getCoveredModelRanges(region); 438 if (coverage != null && coverage.length > 0) { 439 IRegion container= findRegionContainingLine(coverage, line); 440 if (container != null) 441 return convertToLineRange(container); 442 } 443 444 } catch (BadLocationException x) { 445 } 446 447 return null; 448 } 449 450 return lineRange; 451 } 452 453 461 private ILineRange adaptLineRangeToViewport(ILineRange lineRange) { 462 463 try { 464 StyledText text= fSourceViewer.getTextWidget(); 465 466 int topLine= text.getTopIndex(); 467 int rangeTopLine= getWidgetLineNumber(lineRange.getStartLine()); 468 int topDelta= Math.max(topLine - rangeTopLine, 0); 469 470 Rectangle size= text.getClientArea(); 471 Rectangle trim= text.computeTrim(0, 0, 0, 0); 472 int height= size.height - trim.height; 473 474 int lines= JFaceTextUtil.getLineIndex(text, height) - text.getTopIndex(); 475 476 int bottomLine= topLine + lines; 477 478 int rangeBottomLine= getWidgetLineNumber(lineRange.getStartLine() + lineRange.getNumberOfLines() - 1); 479 int bottomDelta= Math.max(rangeBottomLine - bottomLine, 0); 480 481 return new LineRange(lineRange.getStartLine() + topDelta, lineRange.getNumberOfLines() - bottomDelta - topDelta); 482 483 } catch (BadLocationException ex) { 484 } 485 486 return null; 487 } 488 489 496 private IRegion convertToRegion(ILineRange lineRange) throws BadLocationException { 497 IDocument document= fSourceViewer.getDocument(); 498 int startOffset= document.getLineOffset(lineRange.getStartLine()); 499 int endLine= lineRange.getStartLine() + Math.max(0, lineRange.getNumberOfLines() - 1); 500 IRegion lineInfo= document.getLineInformation(endLine); 501 int endOffset= lineInfo.getOffset() + lineInfo.getLength(); 502 return new Region(startOffset, endOffset - startOffset); 503 } 504 505 514 private IRegion findRegionContainingLine(IRegion[] regions, int line) throws BadLocationException { 515 IDocument document= fSourceViewer.getDocument(); 516 IRegion lineInfo= document.getLineInformation(line); 517 for (int i= 0; i < regions.length; i++) { 518 if (TextUtilities.overlaps(regions[i], lineInfo)) 519 return regions[i]; 520 } 521 return null; 522 } 523 524 531 private ILineRange convertToLineRange(IRegion region) throws BadLocationException { 532 IDocument document= fSourceViewer.getDocument(); 533 int startLine= document.getLineOfOffset(region.getOffset()); 534 int endLine= document.getLineOfOffset(region.getOffset() + region.getLength()); 535 return new LineRange(startLine, endLine - startLine + 1); 536 } 537 538 545 private Rectangle computeArea(ILineRange lineRange) { 546 try { 547 StyledText text= fSourceViewer.getTextWidget(); 548 final int startLine= getWidgetLineNumber(lineRange.getStartLine()); 549 int y= JFaceTextUtil.computeLineHeight(text, 0, startLine, startLine) - text.getTopPixel(); 550 int height= JFaceTextUtil.computeLineHeight(text, startLine, startLine + lineRange.getNumberOfLines(), lineRange.getNumberOfLines()); 551 Point size= fVerticalRulerInfo.getControl().getSize(); 552 return new Rectangle(0, y, size.x, height); 553 } catch (BadLocationException x) { 554 } 555 return null; 556 } 557 558 563 private int computeNumberOfVisibleLines() { 564 return LineNumberRulerColumn.getVisibleLinesInViewport(fSourceViewer.getTextWidget()); 566 } 567 568 577 private IAnnotationHover getHover(MouseEvent event) { 578 if (event == null || event.getSource() == null) 579 return fAnnotationHover; 580 581 if (fVerticalRulerInfo instanceof CompositeRuler) { 582 CompositeRuler comp= (CompositeRuler) fVerticalRulerInfo; 583 for (Iterator it= comp.getDecoratorIterator(); it.hasNext();) { 584 Object o= it.next(); 585 if (o instanceof IVerticalRulerInfoExtension && o instanceof IVerticalRulerInfo) { 586 if (((IVerticalRulerInfo) o).getControl() == event.getSource()) { 587 IAnnotationHover hover= ((IVerticalRulerInfoExtension) o).getHover(); 588 if (hover != null) 589 return hover; 590 } 591 } 592 } 593 } 594 return fAnnotationHover; 595 } 596 597 604 private int getHoverLine(MouseEvent event) { 605 return event == null ? -1 : fVerticalRulerInfo.toDocumentLineNumber(event.y); 606 } 607 608 615 private int getWidgetLineNumber(int line) throws BadLocationException { 616 if (fSourceViewer instanceof ITextViewerExtension5) { 617 ITextViewerExtension5 extension= (ITextViewerExtension5) fSourceViewer; 618 return extension.modelLine2WidgetLine(line); 619 } 620 621 IRegion region= fSourceViewer.getVisibleRegion(); 622 int firstLine= fSourceViewer.getDocument().getLineOfOffset(region.getOffset()); 623 return line - firstLine; 624 } 625 626 632 private Rectangle computeArea(int line) { 633 try { 634 StyledText text= fSourceViewer.getTextWidget(); 635 int widgetLine= getWidgetLineNumber(line); 636 int y= JFaceTextUtil.computeLineHeight(text, 0, widgetLine, widgetLine) - text.getTopPixel(); 637 Point size= fVerticalRulerInfo.getControl().getSize(); 638 return new Rectangle(0, y, size.x, text.getLineHeight(text.getOffsetAtLine(widgetLine))); 639 } catch (IllegalArgumentException ex) { 640 } catch (BadLocationException ex) { 641 } 642 return null; 643 } 644 645 651 protected IAnnotationHover getAnnotationHover() { 652 return fAnnotationHover; 653 } 654 655 661 protected ISourceViewer getSourceViewer() { 662 return fSourceViewer; 663 } 664 665 671 protected IVerticalRulerInfo getVerticalRulerInfo() { 672 return fVerticalRulerInfo; 673 } 674 675 679 protected Point computeSizeConstraints(Control subjectControl, Rectangle subjectArea, IInformationControl informationControl) { 680 681 Point constraints= super.computeSizeConstraints(subjectControl, subjectArea, informationControl); 682 683 StyledText styledText= fSourceViewer.getTextWidget(); 684 if (styledText != null) { 685 Rectangle r= styledText.getClientArea(); 686 if (r != null) { 687 constraints.x= r.width; 688 constraints.y= r.height; 689 } 690 } 691 692 return constraints; 693 } 694 695 699 protected Point computeLocation(Rectangle subjectArea, Point controlSize, Anchor anchor) { 700 MouseEvent event= getHoverEvent(); 701 IAnnotationHover hover= getHover(event); 702 703 boolean allowMouseExit= false; 704 if (hover instanceof IAnnotationHoverExtension) { 705 IAnnotationHoverExtension extension= (IAnnotationHoverExtension) hover; 706 allowMouseExit= extension.canHandleMouseCursor(); 707 } 708 boolean hideOnMouseWheel= true; 709 if (hover instanceof IAnnotationHoverExtension2) { 710 IAnnotationHoverExtension2 extension= (IAnnotationHoverExtension2) hover; 711 hideOnMouseWheel= !extension.canHandleMouseWheel(); 712 } 713 fHideOnMouseWheel= hideOnMouseWheel; 714 715 if (allowMouseExit) { 716 fAllowMouseExit= true; 717 718 Control subjectControl= getSubjectControl(); 719 if (anchor == AbstractInformationControlManager.ANCHOR_RIGHT) 721 return subjectControl.toDisplay(subjectArea.x - 4, subjectArea.y - 2); 722 else if (anchor == AbstractInformationControlManager.ANCHOR_LEFT) 723 return subjectControl.toDisplay(subjectArea.x + subjectArea.width - controlSize.x + 4, subjectArea.y - 2); 724 } 725 726 fAllowMouseExit= false; 727 return super.computeLocation(subjectArea, controlSize, anchor); 728 } 729 730 737 public IAnnotationHover getCurrentAnnotationHover() { 738 return fCurrentHover; 739 } 740 } 741 742 | Popular Tags |