org.eclipse.jface.text.source.AnnotationBarHoverManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.eclipse.jface.text Show documentation
Show all versions of org.eclipse.jface.text Show documentation
This is org.eclipse.jface.text jar used by Scout SDK
The newest version!
/*******************************************************************************
* Copyright (c) 2000, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jface.text.source;
import java.util.Iterator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.internal.text.InformationControlReplacer;
import org.eclipse.jface.internal.text.InternalAccessor;
import org.eclipse.jface.text.AbstractHoverInformationControlManager;
import org.eclipse.jface.text.AbstractInformationControlManager;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.ITextViewerExtension8.EnrichMode;
import org.eclipse.jface.text.JFaceTextUtil;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextUtilities;
/**
* This manager controls the layout, content, and visibility of an information
* control in reaction to mouse hover events issued by the vertical ruler of a
* source viewer.
* @since 2.0
*/
public class AnnotationBarHoverManager extends AbstractHoverInformationControlManager {
/**
* The information control closer for the hover information. Closes the information control as soon as the mouse pointer leaves the subject area, a mouse button is pressed, the user presses a key, or the subject control is resized or moved.
*
* @since 3.0
* @deprecated As of 3.4, no longer used as closer from super class is used
*/
@Deprecated
protected class Closer extends MouseTrackAdapter implements IInformationControlCloser, MouseListener, MouseMoveListener, ControlListener, KeyListener, DisposeListener, ShellListener, Listener {
/** The closer's subject control */
private Control fSubjectControl;
/** The subject area */
private Rectangle fSubjectArea;
/** Indicates whether this closer is active */
private boolean fIsActive= false;
/** The information control. */
private IInformationControl fInformationControlToClose;
/**
* true
if a wheel handler is installed.
* @since 3.2
*/
private boolean fHasWheelFilter= false;
/**
* The cached display.
* @since 3.2
*/
private Display fDisplay;
/**
* Creates a new information control closer.
*/
public Closer() {
}
@Override
public void setSubjectControl(Control control) {
fSubjectControl= control;
}
/*
* @see IInformationControlCloser#setHoverControl(IHoverControl)
*/
@Override
public void setInformationControl(IInformationControl control) {
fInformationControlToClose= control;
}
@Override
public void start(Rectangle subjectArea) {
if (fIsActive) return;
fIsActive= true;
fSubjectArea= subjectArea;
fInformationControlToClose.addDisposeListener(this);
if (fSubjectControl != null && !fSubjectControl.isDisposed()) {
fSubjectControl.addMouseListener(this);
fSubjectControl.addMouseMoveListener(this);
fSubjectControl.addMouseTrackListener(this);
fSubjectControl.getShell().addShellListener(this);
fSubjectControl.addControlListener(this);
fSubjectControl.addKeyListener(this);
fDisplay= fSubjectControl.getDisplay();
if (!fDisplay.isDisposed() && fHideOnMouseWheel) {
fHasWheelFilter= true;
fDisplay.addFilter(SWT.MouseHorizontalWheel, this);
fDisplay.addFilter(SWT.MouseVerticalWheel, this);
}
}
}
@Override
public void stop() {
if (!fIsActive)
return;
fIsActive= false;
if (fSubjectControl != null && !fSubjectControl.isDisposed()) {
fSubjectControl.removeMouseListener(this);
fSubjectControl.removeMouseMoveListener(this);
fSubjectControl.removeMouseTrackListener(this);
fSubjectControl.getShell().removeShellListener(this);
fSubjectControl.removeControlListener(this);
fSubjectControl.removeKeyListener(this);
}
if (fDisplay != null && !fDisplay.isDisposed() && fHasWheelFilter) {
fDisplay.removeFilter(SWT.MouseHorizontalWheel, this);
fDisplay.removeFilter(SWT.MouseVerticalWheel, this);
}
fHasWheelFilter= false;
fDisplay= null;
}
/**
* Stops the information control and if delayRestart
is set allows restart only after a certain delay.
*
* @param delayRestart true
if restart should be delayed
* @deprecated As of 3.4, replaced by {@link #stop()}. Note that delayRestart
was never honored.
*/
@Deprecated
protected void stop(boolean delayRestart) {
stop();
}
@Override
public void mouseMove(MouseEvent event) {
if (!fSubjectArea.contains(event.x, event.y))
hideInformationControl();
}
@Override
public void mouseUp(MouseEvent event) {
}
@Override
public void mouseDown(MouseEvent event) {
hideInformationControl();
}
@Override
public void mouseDoubleClick(MouseEvent event) {
hideInformationControl();
}
@Override
public void handleEvent(Event event) {
if (event.type == SWT.MouseHorizontalWheel || event.type == SWT.MouseVerticalWheel)
hideInformationControl();
}
@Override
public void mouseExit(MouseEvent event) {
if (!fAllowMouseExit)
hideInformationControl();
}
@Override
public void controlResized(ControlEvent event) {
hideInformationControl();
}
@Override
public void controlMoved(ControlEvent event) {
hideInformationControl();
}
@Override
public void keyReleased(KeyEvent event) {
}
@Override
public void keyPressed(KeyEvent event) {
hideInformationControl();
}
@Override
public void shellActivated(ShellEvent e) {
}
@Override
public void shellClosed(ShellEvent e) {
}
@Override
public void shellDeactivated(ShellEvent e) {
hideInformationControl();
}
@Override
public void shellDeiconified(ShellEvent e) {
}
@Override
public void shellIconified(ShellEvent e) {
}
@Override
public void widgetDisposed(DisposeEvent e) {
hideInformationControl();
}
}
/** The source viewer the manager is connected to */
private ISourceViewer fSourceViewer;
/** The vertical ruler the manager is registered with */
private IVerticalRulerInfo fVerticalRulerInfo;
/** The annotation hover the manager uses to retrieve the information to display. Can be null
. */
private IAnnotationHover fAnnotationHover;
/**
* Indicates whether the mouse cursor is allowed to leave the subject area without closing the hover.
* @since 3.0
*/
protected boolean fAllowMouseExit= false;
/**
* Whether we should hide the over on mouse wheel action.
*
* @since 3.2
*/
private boolean fHideOnMouseWheel= true;
/**
* The current annotation hover.
* @since 3.2
*/
private IAnnotationHover fCurrentHover;
/**
* Creates an annotation hover manager with the given parameters. In addition,
* the hovers anchor is RIGHT and the margin is 5 points to the right.
*
* @param sourceViewer the source viewer this manager connects to
* @param ruler the vertical ruler this manager connects to
* @param annotationHover the annotation hover providing the information to be displayed
* @param creator the information control creator
* @deprecated As of 2.1, replaced by {@link AnnotationBarHoverManager#AnnotationBarHoverManager(IVerticalRulerInfo, ISourceViewer, IAnnotationHover, IInformationControlCreator)}
*/
@Deprecated
public AnnotationBarHoverManager(ISourceViewer sourceViewer, IVerticalRuler ruler, IAnnotationHover annotationHover, IInformationControlCreator creator) {
this(ruler, sourceViewer, annotationHover, creator);
}
/**
* Creates an annotation hover manager with the given parameters. In addition,
* the hovers anchor is RIGHT and the margin is 5 points to the right.
*
* @param rulerInfo the vertical ruler this manager connects to
* @param sourceViewer the source viewer this manager connects to
* @param annotationHover the annotation hover providing the information to be displayed or null
if none
* @param creator the information control creator
* @since 2.1
*/
public AnnotationBarHoverManager(IVerticalRulerInfo rulerInfo, ISourceViewer sourceViewer, IAnnotationHover annotationHover, IInformationControlCreator creator) {
super(creator);
Assert.isNotNull(sourceViewer);
fSourceViewer= sourceViewer;
fVerticalRulerInfo= rulerInfo;
fAnnotationHover= annotationHover;
setAnchor(ANCHOR_RIGHT);
setMargins(5, 0);
// use closer from super class
}
@Override
protected void computeInformation() {
fAllowMouseExit= false;
MouseEvent event= getHoverEvent();
if ((event.stateMask & SWT.BUTTON_MASK) != 0) {
setInformation(null, null);
return;
}
IAnnotationHover hover= getHover(event);
if (hover == null) {
setInformation(null, null);
return;
}
int line= getHoverLine(event);
if (hover instanceof IAnnotationHoverExtension) {
IAnnotationHoverExtension extension= (IAnnotationHoverExtension) hover;
ILineRange range= extension.getHoverLineRange(fSourceViewer, line);
setCustomInformationControlCreator(extension.getHoverControlCreator());
range= adaptLineRange(range, line);
if (range != null)
setInformation(extension.getHoverInfo(fSourceViewer, range, computeNumberOfVisibleLines()), computeArea(range));
else
setInformation(null, null);
} else {
setCustomInformationControlCreator(null);
setInformation(hover.getHoverInfo(fSourceViewer, line), computeArea(line));
}
}
@Override
protected void showInformationControl(Rectangle subjectArea) {
super.showInformationControl(subjectArea);
fCurrentHover= getHover(getHoverEvent());
}
@Override
protected void hideInformationControl() {
fCurrentHover= null;
super.hideInformationControl();
}
/**
* Adapts a given line range so that the result is a line range that does
* not overlap with any collapsed region and fits into the view port of the
* attached viewer.
*
* @param lineRange the original line range
* @param line the anchor line
* @return the adapted line range
* @since 3.0
*/
private ILineRange adaptLineRange(ILineRange lineRange, int line) {
if (lineRange != null) {
lineRange= adaptLineRangeToFolding(lineRange, line);
if (lineRange != null)
return adaptLineRangeToViewport(lineRange);
}
return null;
}
/**
* Adapts a given line range so that the result is a line range that does
* not overlap with any collapsed region of the attached viewer.
*
* @param lineRange the original line range
* @param line the anchor line
* @return the adapted line range
* @since 3.0
*/
private ILineRange adaptLineRangeToFolding(ILineRange lineRange, int line) {
if (fSourceViewer instanceof ITextViewerExtension5) {
ITextViewerExtension5 extension= (ITextViewerExtension5) fSourceViewer;
try {
IRegion region= convertToRegion(lineRange);
IRegion[] coverage= extension.getCoveredModelRanges(region);
if (coverage != null && coverage.length > 0) {
IRegion container= findRegionContainingLine(coverage, line);
if (container != null)
return convertToLineRange(container);
}
} catch (BadLocationException x) {
}
return null;
}
return lineRange;
}
/**
* Adapts a given line range so that the result is a line range that fits
* into the view port of the attached viewer.
*
* @param lineRange the original line range
* @return the adapted line range
* @since 3.0
*/
private ILineRange adaptLineRangeToViewport(ILineRange lineRange) {
try {
StyledText text= fSourceViewer.getTextWidget();
int topLine= text.getTopIndex();
int rangeTopLine= getWidgetLineNumber(lineRange.getStartLine());
int topDelta= Math.max(topLine - rangeTopLine, 0);
Rectangle size= text.getClientArea();
Rectangle trim= text.computeTrim(0, 0, 0, 0);
int height= size.height - trim.height;
int lines= JFaceTextUtil.getLineIndex(text, height) - text.getTopIndex();
int bottomLine= topLine + lines;
int rangeBottomLine= getWidgetLineNumber(lineRange.getStartLine() + lineRange.getNumberOfLines() - 1);
int bottomDelta= Math.max(rangeBottomLine - bottomLine, 0);
return new LineRange(lineRange.getStartLine() + topDelta, lineRange.getNumberOfLines() - bottomDelta - topDelta);
} catch (BadLocationException ex) {
}
return null;
}
/**
* Converts a line range into a character range.
*
* @param lineRange the line range
* @return the corresponding character range
* @throws BadLocationException in case the given line range is invalid
*/
private IRegion convertToRegion(ILineRange lineRange) throws BadLocationException {
IDocument document= fSourceViewer.getDocument();
int startOffset= document.getLineOffset(lineRange.getStartLine());
int endLine= lineRange.getStartLine() + Math.max(0, lineRange.getNumberOfLines() - 1);
IRegion lineInfo= document.getLineInformation(endLine);
int endOffset= lineInfo.getOffset() + lineInfo.getLength();
return new Region(startOffset, endOffset - startOffset);
}
/**
* Returns the region out of the given set that contains the given line or
* null
.
*
* @param regions the set of regions
* @param line the line
* @return the region of the set that contains the line
* @throws BadLocationException in case line is invalid
*/
private IRegion findRegionContainingLine(IRegion[] regions, int line) throws BadLocationException {
IDocument document= fSourceViewer.getDocument();
IRegion lineInfo= document.getLineInformation(line);
for (int i= 0; i < regions.length; i++) {
if (TextUtilities.overlaps(regions[i], lineInfo))
return regions[i];
}
return null;
}
/**
* Converts a given character region into a line range.
*
* @param region the character region
* @return the corresponding line range
* @throws BadLocationException in case the given region in invalid
*/
private ILineRange convertToLineRange(IRegion region) throws BadLocationException {
IDocument document= fSourceViewer.getDocument();
int startLine= document.getLineOfOffset(region.getOffset());
int endLine= document.getLineOfOffset(region.getOffset() + region.getLength());
return new LineRange(startLine, endLine - startLine + 1);
}
/**
* Returns the visible area of the vertical ruler covered by the given line
* range.
*
* @param lineRange the line range
* @return the visible area
*/
private Rectangle computeArea(ILineRange lineRange) {
try {
StyledText text= fSourceViewer.getTextWidget();
final int startLine= getWidgetLineNumber(lineRange.getStartLine());
int y= JFaceTextUtil.computeLineHeight(text, 0, startLine, startLine) - text.getTopPixel();
int height= JFaceTextUtil.computeLineHeight(text, startLine, startLine + lineRange.getNumberOfLines(), lineRange.getNumberOfLines());
Point size= fVerticalRulerInfo.getControl().getSize();
return new Rectangle(0, y, size.x, height);
} catch (BadLocationException x) {
}
return null;
}
/**
* Returns the number of the currently visible lines.
*
* @return the number of the currently visible lines
*/
private int computeNumberOfVisibleLines() {
StyledText textWidget= fSourceViewer.getTextWidget();
int lineHeight= textWidget.getLineHeight();
int clientAreaHeight= textWidget.getClientArea().height;
return clientAreaHeight / lineHeight;
}
/**
* Determines the hover to be used to display information based on the source of the
* mouse hover event. If fVerticalRulerInfo
is not a composite ruler, the
* standard hover is returned.
*
* @param event the source of the mouse hover event
* @return the hover depending on source
, or fAnnotationHover
if none can be found.
* @since 3.0
*/
private IAnnotationHover getHover(MouseEvent event) {
if (event == null || event.getSource() == null)
return fAnnotationHover;
if (fVerticalRulerInfo instanceof CompositeRuler) {
CompositeRuler comp= (CompositeRuler) fVerticalRulerInfo;
for (Iterator it= comp.getDecoratorIterator(); it.hasNext();) {
Object o= it.next();
if (o instanceof IVerticalRulerInfoExtension && o instanceof IVerticalRulerInfo) {
if (((IVerticalRulerInfo) o).getControl() == event.getSource()) {
IAnnotationHover hover= ((IVerticalRulerInfoExtension) o).getHover();
if (hover != null)
return hover;
}
}
}
}
return fAnnotationHover;
}
/**
* Returns the line of interest deduced from the mouse hover event.
*
* @param event a mouse hover event that triggered hovering
* @return the document model line number on which the hover event occurred or -1
if there is no event
* @since 3.0
*/
private int getHoverLine(MouseEvent event) {
return event == null ? -1 : fVerticalRulerInfo.toDocumentLineNumber(event.y);
}
/**
* Returns for the widget line number for the given document line number.
*
* @param line the absolute line number
* @return the line number relative to the viewer's visible region
* @throws BadLocationException if line
is not valid in the viewer's document
*/
private int getWidgetLineNumber(int line) throws BadLocationException {
if (fSourceViewer instanceof ITextViewerExtension5) {
ITextViewerExtension5 extension= (ITextViewerExtension5) fSourceViewer;
return extension.modelLine2WidgetLine(line);
}
IRegion region= fSourceViewer.getVisibleRegion();
int firstLine= fSourceViewer.getDocument().getLineOfOffset(region.getOffset());
return line - firstLine;
}
/**
* Determines graphical area covered by the given line.
*
* @param line the number of the line in the viewer whose graphical extend in the vertical ruler must be computed
* @return the graphical extend of the given line
*/
private Rectangle computeArea(int line) {
try {
StyledText text= fSourceViewer.getTextWidget();
int widgetLine= getWidgetLineNumber(line);
int y= JFaceTextUtil.computeLineHeight(text, 0, widgetLine, widgetLine) - text.getTopPixel();
Point size= fVerticalRulerInfo.getControl().getSize();
return new Rectangle(0, y, size.x, text.getLineHeight(text.getOffsetAtLine(widgetLine)));
} catch (IllegalArgumentException ex) {
} catch (BadLocationException ex) {
}
return null;
}
/**
* Returns the annotation hover for this hover manager.
*
* @return the annotation hover for this hover manager or null
if none
* @since 2.1
*/
protected IAnnotationHover getAnnotationHover() {
return fAnnotationHover;
}
/**
* Returns the source viewer for this hover manager.
*
* @return the source viewer for this hover manager
* @since 2.1
*/
protected ISourceViewer getSourceViewer() {
return fSourceViewer;
}
/**
* Returns the vertical ruler info for this hover manager
*
* @return the vertical ruler info for this hover manager
* @since 2.1
*/
protected IVerticalRulerInfo getVerticalRulerInfo() {
return fVerticalRulerInfo;
}
@Override
protected Point computeSizeConstraints(Control subjectControl, Rectangle subjectArea, IInformationControl informationControl) {
Point constraints= super.computeSizeConstraints(subjectControl, subjectArea, informationControl);
// make as big as text area, if possible
StyledText styledText= fSourceViewer.getTextWidget();
if (styledText != null) {
Rectangle r= styledText.getClientArea();
if (r != null) {
constraints.x= r.width;
constraints.y= r.height;
}
}
return constraints;
}
@Override
protected Point computeInformationControlLocation(Rectangle subjectArea, Point controlSize) {
MouseEvent event= getHoverEvent();
IAnnotationHover hover= getHover(event);
if (hover instanceof IAnnotationHoverExtension) {
IAnnotationHoverExtension extension= (IAnnotationHoverExtension) hover;
boolean allowMouseExit= extension.canHandleMouseCursor();
if (allowMouseExit) {
return computeLocation(subjectArea, controlSize, ANCHOR_RIGHT);
}
}
return super.computeInformationControlLocation(subjectArea, controlSize);
}
@Override
protected Point computeLocation(Rectangle subjectArea, Point controlSize, Anchor anchor) {
MouseEvent event= getHoverEvent();
IAnnotationHover hover= getHover(event);
boolean allowMouseExit= false;
if (hover instanceof IAnnotationHoverExtension) {
IAnnotationHoverExtension extension= (IAnnotationHoverExtension) hover;
allowMouseExit= extension.canHandleMouseCursor();
}
boolean hideOnMouseWheel= true;
if (hover instanceof IAnnotationHoverExtension2) {
IAnnotationHoverExtension2 extension= (IAnnotationHoverExtension2) hover;
hideOnMouseWheel= !extension.canHandleMouseWheel();
}
fHideOnMouseWheel= hideOnMouseWheel;
if (allowMouseExit) {
fAllowMouseExit= true;
Control subjectControl= getSubjectControl();
// return a location that just overlaps the annotation on the bar
if (anchor == AbstractInformationControlManager.ANCHOR_RIGHT)
return subjectControl.toDisplay(subjectArea.x - 4, subjectArea.y - 2);
else if (anchor == AbstractInformationControlManager.ANCHOR_LEFT)
return subjectControl.toDisplay(subjectArea.x + subjectArea.width - controlSize.x + 4, subjectArea.y - 2);
}
fAllowMouseExit= false;
return super.computeLocation(subjectArea, controlSize, anchor);
}
/**
* Returns the currently shown annotation hover or null
if none
* hover is shown.
*
* @return the currently shown annotation hover or null
* @since 3.2
*/
public IAnnotationHover getCurrentAnnotationHover() {
return fCurrentHover;
}
/**
* Returns an adapter that gives access to internal methods.
*
* Note: This method is not intended to be referenced or overridden by clients.
*
*
* @return the replaceable information control accessor
* @since 3.4
* @noreference This method is not intended to be referenced by clients.
* @nooverride This method is not intended to be re-implemented or extended by clients.
*/
@Override
public InternalAccessor getInternalAccessor() {
return new InternalAccessor() {
@Override
public IInformationControl getCurrentInformationControl() {
return AnnotationBarHoverManager.super.getInternalAccessor().getCurrentInformationControl();
}
@Override
public void setInformationControlReplacer(InformationControlReplacer replacer) {
AnnotationBarHoverManager.super.getInternalAccessor().setInformationControlReplacer(replacer);
}
@Override
public InformationControlReplacer getInformationControlReplacer() {
return AnnotationBarHoverManager.super.getInternalAccessor().getInformationControlReplacer();
}
@Override
public boolean canReplace(IInformationControl control) {
return AnnotationBarHoverManager.super.getInternalAccessor().canReplace(control);
}
@Override
public boolean isReplaceInProgress() {
return AnnotationBarHoverManager.super.getInternalAccessor().isReplaceInProgress();
}
@Override
public void replaceInformationControl(boolean takeFocus) {
AnnotationBarHoverManager.super.getInternalAccessor().replaceInformationControl(takeFocus);
}
@Override
public void cropToClosestMonitor(Rectangle bounds) {
AnnotationBarHoverManager.super.getInternalAccessor().cropToClosestMonitor(bounds);
}
@Override
public void setHoverEnrichMode(EnrichMode mode) {
AnnotationBarHoverManager.super.getInternalAccessor().setHoverEnrichMode(mode);
}
@Override
public boolean getAllowMouseExit() {
return fAllowMouseExit;
}
};
}
}