Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: 8a9647f356b0b38b9282f40a16ce0d3a3e88adf4 (plain) (tree)



















                                                                                                      

                                                    
                                            





                                                                                       
              


























































                                                                                                                             
                                                                                                             



                                                                                                              
                 


















































































                                                                                                                                      
/**
 *  Copyright (c) 2017 Angelo ZERR.
 *  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:
 *  Angelo Zerr <angelo.zerr@gmail.com> - [CodeMining] Provide inline annotations support - Bug 527675
 */
package org.eclipse.jface.text.source.inlined;

import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.GlyphMetrics;
import org.eclipse.swt.graphics.Rectangle;

import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.JFaceTextUtil;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.AnnotationPainter.IDrawingStrategy;

/**
 * {@link IDrawingStrategy} implementation to render {@link AbstractInlinedAnnotation}.
 *
 * @since 3.13
 */
class InlinedAnnotationDrawingStrategy implements IDrawingStrategy {

	@Override
	public void draw(Annotation annotation, GC gc, StyledText textWidget, int offset, int length, Color color) {
		if (!(annotation instanceof AbstractInlinedAnnotation)) {
			return;
		}
		InlinedAnnotationDrawingStrategy.draw((AbstractInlinedAnnotation) annotation, gc, textWidget, offset, length,
				color);
	}

	/**
	 * Draw the inlined annotation.
	 *
	 * @param annotation the annotation to be drawn
	 * @param gc the graphics context, <code>null</code> when in clearing mode
	 * @param textWidget the text widget to draw on
	 * @param offset the offset of the line
	 * @param length the length of the line
	 * @param color the color of the line
	 */
	public static void draw(AbstractInlinedAnnotation annotation, GC gc, StyledText textWidget, int offset, int length,
			Color color) {
		if (annotation.isMarkedDeleted()) {
			// When annotation is deleted, redraw the styled text to hide old draw of
			// annotations
			textWidget.redraw();
			// update caret offset since line spacing has changed.
			textWidget.setCaretOffset(textWidget.getCaretOffset());
			return;
		}
		if (annotation instanceof LineHeaderAnnotation) {
			draw((LineHeaderAnnotation) annotation, gc, textWidget, offset, length, color);
		} else {
			draw((LineContentAnnotation) annotation, gc, textWidget, offset, length, color);
		}
	}

	/**
	 * Draw the line header annotation in the line spacing of the previous line.
	 *
	 * @param annotation the annotation to be drawn
	 * @param gc the graphics context, <code>null</code> when in clearing mode
	 * @param textWidget the text widget to draw on
	 * @param offset the offset of the line
	 * @param length the length of the line
	 * @param color the color of the line
	 */
	private static void draw(LineHeaderAnnotation annotation, GC gc, StyledText textWidget, int offset, int length,
			Color color) {
		// compute current, previous line index.
		int lineIndex= -1;
		try {
			lineIndex= textWidget.getLineAtOffset(offset);
		} catch (Exception e) {
			return;
		}
		int previousLineIndex= lineIndex - 1;
		// check the previous line index where annotation must be drawn in line spacing is not hidden
		ITextViewer viewer= annotation.getViewer();
		int firstLineIndex= JFaceTextUtil.getPartialTopIndex(viewer);
		if (viewer instanceof ITextViewerExtension5) {
			firstLineIndex= ((ITextViewerExtension5) viewer).modelLine2WidgetLine(firstLineIndex);
		}
		if (gc != null) {
			// Compute the location of the annotation
			int x= textWidget.getLocationAtOffset(offset).x;
			int y= 0;
			int height= annotation.getHeight();
			if (lineIndex > 0) {
				int previousOffset= textWidget.getOffsetAtLine(previousLineIndex);
				y= textWidget.getLocationAtOffset(previousOffset).y + height;
			}
			Rectangle clipping= gc.getClipping();
			if (clipping.contains(x, y)) {
				// GC clipping contains the x, y where annotation must be drawn.

				// Colorize line spacing area with the background of StyledText to avoid having highlighted line color
				gc.setBackground(textWidget.getBackground());
				Rectangle client= textWidget.getClientArea();
				textWidget.drawBackground(gc, x, y, client.width, height);

				// draw the annotation
				annotation.draw(gc, textWidget, offset, length, color, x, y);
				return;
			} else {
				if (!(clipping.y - height == y)) {
					// Clipping doesn't include the y of previous line spacing, stop the redraw
					// range.
					return;
				}
			}
		}

		if (previousLineIndex < 0) {
			// There are none previous line, do nothing
			return;
		}
		// refresh the previous line range where line header annotation must be drawn.
		int previousOffset= textWidget.getOffsetAtLine(previousLineIndex);
		int lineLength= offset - previousOffset;
		textWidget.redrawRange(previousOffset, lineLength, true);
	}

	/**
	 * Draw the line content annotation inside line in the empty area computed by
	 * {@link GlyphMetrics}.
	 *
	 * @param annotation the annotation to be drawn
	 * @param gc the graphics context, <code>null</code> when in clearing mode
	 * @param textWidget the text widget to draw on
	 * @param offset the offset of the line
	 * @param length the length of the line
	 * @param color the color of the line
	 */
	private static void draw(LineContentAnnotation annotation, GC gc, StyledText textWidget, int offset, int length,
			Color color) {
		if (gc != null) {
			// Compute the location of the annotation
			FontMetrics fontMetrics= gc.getFontMetrics();
			Rectangle bounds= textWidget.getTextBounds(offset, offset);
			int x= bounds.x + fontMetrics.getLeading();
			int y= bounds.y + fontMetrics.getDescent();

			// Draw the line content annotation
			annotation.draw(gc, textWidget, offset, length, color, x, y);

			// The inline annotation replaces one character by taking a place width
			// GlyphMetrics
			// Here we need to redraw this first character because GlyphMetrics clip this
			// character.
			String s= textWidget.getText(offset, offset);
			StyleRange style= textWidget.getStyleRangeAtOffset(offset);
			if (style != null) {
				if (style.background != null) {
					gc.setBackground(style.background);
				}
				if (style.foreground != null) {
					gc.setForeground(style.foreground);
				}
			}
			gc.drawString(s, bounds.x + bounds.width - gc.stringExtent(s).x, bounds.y, true);
		} else {
			textWidget.redrawRange(offset, length, true);
		}
	}
}

Back to the top