/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jface.text.source;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.ScrollBar;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextListener;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.JFaceTextUtil;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextEvent;
import org.eclipse.jface.text.source.projection.AnnotationBag;


/**
 * Ruler presented next to a source viewer showing all annotations of the viewer's annotation model
 * in a compact format. The ruler has the same height as the source viewer.
 * <p>
 * This overview ruler uses non-saturated colors unless {@link #setUseSaturatedColors(boolean)} gets
 * called.
 * </p>
 * <p>
 * Clients usually instantiate and configure objects of this class.
 * </p>
 *
 * @since 2.1
 */
public class OverviewRuler implements IOverviewRulerExtension, IOverviewRuler {

	/**
	 * Internal listener class.
	 */
	class InternalListener implements ITextListener, IAnnotationModelListener, IAnnotationModelListenerExtension {

		/*
		 * @see ITextListener#textChanged
		 */
		@Override
		public void textChanged(TextEvent e) {
			if (fTextViewer != null && e.getDocumentEvent() == null && e.getViewerRedrawState()) {
				// handle only changes of visible document
				redraw();
			}
		}

		@Override
		public void modelChanged(IAnnotationModel model) {
			update();
		}

		@Override
		public void modelChanged(AnnotationModelEvent event) {
			if (!event.isValid())
				return;

			if (event.isWorldChange()) {
				update();
				return;
			}

			Annotation[] annotations= event.getAddedAnnotations();
			int length= annotations.length;
			for (int i= 0; i < length; i++) {
				if (!skip(annotations[i].getType())) {
					update();
					return;
				}
			}

			annotations= event.getRemovedAnnotations();
			length= annotations.length;
			for (int i= 0; i < length; i++) {
				if (!skip(annotations[i].getType())) {
					update();
					return;
				}
			}

			annotations= event.getChangedAnnotations();
			length= annotations.length;
			for (int i= 0; i < length; i++) {
				if (!skip(annotations[i].getType())) {
					update();
					return;
				}
			}

		}
	}

	/**
	 * Enumerates the annotations of a specified type and characteristics
	 * of the associated annotation model.
	 */
	class FilterIterator implements Iterator<Annotation> {

		final static int TEMPORARY= 1 << 1;
		final static int PERSISTENT= 1 << 2;
		final static int IGNORE_BAGS= 1 << 3;

		private Iterator<Annotation> fIterator;
		private Object fType;
		private Annotation fNext;
		private int fStyle;

		/**
		 * Creates a new filter iterator with the given specification.
		 *
		 * @param annotationType the annotation type
		 * @param style the style
		 */
		public FilterIterator(Object annotationType, int style) {
			fType= annotationType;
			fStyle= style;
			if (fModel != null) {
				fIterator= fModel.getAnnotationIterator();
				skip();
			}
		}

		/**
		 * Creates a new filter iterator with the given specification.
		 *
		 * @param annotationType the annotation type
		 * @param style the style
		 * @param iterator the iterator
		 */
		public FilterIterator(Object annotationType, int style, Iterator<Annotation> iterator) {
			fType= annotationType;
			fStyle= style;
			fIterator= iterator;
			skip();
		}

		private void skip() {

			boolean temp= (fStyle & TEMPORARY) != 0;
			boolean pers= (fStyle & PERSISTENT) != 0;
			boolean ignr= (fStyle & IGNORE_BAGS) != 0;

			while (fIterator.hasNext()) {
				Annotation next= fIterator.next();

				if (next.isMarkedDeleted())
					continue;

				if (ignr && (next instanceof AnnotationBag))
					continue;

				fNext= next;
				Object annotationType= next.getType();
				if (fType == null || fType.equals(annotationType) || !fConfiguredAnnotationTypes.contains(annotationType) && isSubtype(annotationType)) {
					if (temp && pers) return;
					if (pers && next.isPersistent()) return;
					if (temp && !next.isPersistent()) return;
				}
			}
			fNext= null;
		}

		private boolean isSubtype(Object annotationType) {
			if (fAnnotationAccess instanceof  IAnnotationAccessExtension) {
				IAnnotationAccessExtension extension= (IAnnotationAccessExtension) fAnnotationAccess;
				return extension.isSubtype(annotationType, fType);
			}
			return fType.equals(annotationType);
		}

		@Override
		public boolean hasNext() {
			return fNext != null;
		}
		@Override
		public Annotation next() {
			try {
				return fNext;
			} finally {
				if (fIterator != null)
					skip();
			}
		}
		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}
	}

	/**
	 * The painter of the overview ruler's header.
	 */
	class HeaderPainter implements PaintListener {

		private Color fIndicatorColor;
		private Color fSeparatorColor;

		/**
		 * Creates a new header painter.
		 */
		public HeaderPainter() {
			fSeparatorColor= fHeader.getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
		}

		/**
		 * Sets the header color.
		 *
		 * @param color the header color
		 */
		public void setColor(Color color) {
			fIndicatorColor= color;
		}

		private void drawBevelRect(GC gc, int x, int y, int w, int h, Color topLeft, Color bottomRight) {
			gc.setForeground(topLeft);
			gc.drawLine(x, y, x + w -1, y);
			gc.drawLine(x, y, x, y + h -1);

			gc.setForeground(bottomRight);
			gc.drawLine(x + w, y, x + w, y + h);
			gc.drawLine(x, y + h, x + w, y + h);
		}

		@Override
		public void paintControl(PaintEvent e) {
			if (fIndicatorColor == null)
				return;

			Point s= fHeader.getSize();

			e.gc.setBackground(fIndicatorColor);

			Rectangle headerBounds= fHeader.getBounds();
			boolean isOnTop= headerBounds.y + headerBounds.height <= fCanvas.getLocation().y;
			boolean isTall= s.y > s.x + 2*ANNOTATION_HEIGHT;
			int y;
			if (!isOnTop) {
				// not on top -> attach to bottom
				y= s.y - 3*ANNOTATION_HEIGHT;
			} else if (isTall) {
				// attach to top
				y= ANNOTATION_HEIGHT;
			} else {
				// center
				y= (s.y - (2*ANNOTATION_HEIGHT)) / 2;
			}
			Rectangle r= new Rectangle(INSET, y, s.x - (2*INSET), 2*ANNOTATION_HEIGHT);
			e.gc.fillRectangle(r);

//			Display d= fHeader.getDisplay();
//			drawBevelRect(e.gc, r.x, r.y, r.width -1, r.height -1, d.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW), d.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW));
			drawBevelRect(e.gc, r.x, r.y, r.width -1, r.height -1, fSeparatorColor, fSeparatorColor);

			e.gc.setForeground(fSeparatorColor);
			e.gc.setLineWidth(0); // NOTE: 0 means width is 1 but with optimized performance

			if (!isOnTop || !isTall) {
				// only draw separator if at bottom or if gap is small
				e.gc.drawLine(0, s.y -1, s.x -1, s.y -1);
			}
		}
	}

	/**
	 * Container for cached widget infos.
	 *
	 * @since 3.7
	 */
	private static class WidgetInfos {
		/**
		 * the text widget line count
		 */
		int maxLines;
		/**
		 * the height of the vertical scrollbar thumb
		 */
		int thumbHeight;
		/**
		 * the visible lines of the text widget
		 */
		double visibleLines;
		/**
		 * the invisible lines of the text widget
		 */
		double invisibleLines;
		/**
		 * the bounds of {@link OverviewRuler#fCanvas}
		 */
		Rectangle bounds;

		/**
		 * the writable area in the text widget (height of all lines in pixels), if smaller than
		 * bounds.height; otherwise an unspecified value &gt;= bounds.height
		 */
		int writable;

		/**
		 * Initializes the widget infos.
		 *
		 * @param textWidget the text widget
		 * @param canvas the overview ruler canvas
		 */
		public WidgetInfos(StyledText textWidget, Canvas canvas) {
			maxLines= textWidget.getLineCount();
			bounds= canvas.getBounds();
			// writeable is of interest only if it is smaller than bounds.height.
			int w= 0;
			for (int i= 0; i < maxLines && w < bounds.height; i++) {
				w+= JFaceTextUtil.computeLineHeight(textWidget, i);
			}
			writable= w;

			ScrollBar verticalBar= textWidget.getVerticalBar();
			if (verticalBar != null && !verticalBar.getVisible()) {
				// Note: when the vertical bar is invisible, the thumbHeight is not reliable,
				// so, we'll compute what would be the thumbHeight in case it was visible.
				int max= verticalBar.getMaximum();
				double clientAreaHeight= textWidget.getClientArea().height;
				if (max > clientAreaHeight) {
					double percentage= clientAreaHeight / max;
					thumbHeight= (int) (bounds.height * percentage);
				} else {
					thumbHeight= bounds.height;
				}
				if (thumbHeight < 0) {
					thumbHeight= 0;
				}
			} else {
				thumbHeight= verticalBar != null ? Math.max(Math.min(bounds.height, verticalBar.getThumbBounds().height), 0) : 0;
			}

			int partialTopIndex= JFaceTextUtil.getPartialTopIndex(textWidget);
			int topLineHeight= textWidget.getLineHeight(textWidget.getOffsetAtLine(partialTopIndex));
			int topLinePixel= textWidget.getLinePixel(partialTopIndex);
			double topIndex= partialTopIndex - (double) topLinePixel / topLineHeight;

			int partialBottomIndex= JFaceTextUtil.getPartialBottomIndex(textWidget);
			int bottomLineHeight= textWidget.getLineHeight(textWidget.getOffsetAtLine(partialBottomIndex));
			int bottomLinePixel= textWidget.getLinePixel(partialBottomIndex);
			double bottomIndex= partialBottomIndex - ((double) bottomLinePixel - textWidget.getClientArea().height) / bottomLineHeight;

			visibleLines= bottomIndex - topIndex;
			invisibleLines= maxLines - visibleLines;
		}
	}

	private static final boolean DEBUG_DRAW= false;
	private static final boolean DEBUG_COMPUTE_Y= false;
	private static final boolean DEBUG_TO_DOCUMENT_LINE_NUMBER= false;

	private static final int INSET= 2;
	private static final int ANNOTATION_HEIGHT= 4;
	private static boolean ANNOTATION_HEIGHT_SCALABLE= true;


	/** The model of the overview ruler */
	private IAnnotationModel fModel;
	/** The view to which this ruler is connected */
	private ITextViewer fTextViewer;
	/** The ruler's canvas */
	private Canvas fCanvas;
	/** The ruler's header */
	private Canvas fHeader;
	/** The buffer for double buffering */
	private Image fBuffer;
	/** The internal listener */
	private InternalListener fInternalListener= new InternalListener();
	/** The width of this vertical ruler */
	private int fWidth;
	/** The hit detection cursor. Do not dispose. */
	private Cursor fHitDetectionCursor;
	/** The last cursor. Do not dispose. */
	private Cursor fLastCursor;
	/** The line of the last mouse button activity */
	private int fLastMouseButtonActivityLine= -1;
	/** The actual annotation height */
	private int fAnnotationHeight= -1;
	/** The annotation access */
	private IAnnotationAccess fAnnotationAccess;
	/** The header painter */
	private HeaderPainter fHeaderPainter;
	/**
	 * The list of annotation types to be shown in this ruler.
	 * @since 3.0
	 */
	private Set<Object> fConfiguredAnnotationTypes= new HashSet<>();
	/**
	 * The list of annotation types to be shown in the header of this ruler.
	 * @since 3.0
	 */
	private Set<Object> fConfiguredHeaderAnnotationTypes= new HashSet<>();
	/** The mapping between annotation types and colors */
	private Map<Object, Color> fAnnotationTypes2Colors= new HashMap<>();
	/** The color manager */
	private ISharedTextColors fSharedTextColors;
	/**
	 * All available annotation types sorted by layer.
	 *
	 * @since 3.0
	 */
	private List<Object> fAnnotationsSortedByLayer= new ArrayList<>();
	/**
	 * All available layers sorted by layer.
	 * This list may contain duplicates.
	 * @since 3.0
	 */
	private List<Integer> fLayersSortedByLayer= new ArrayList<>();
	/**
	 * Map of allowed annotation types.
	 * An allowed annotation type maps to <code>true</code>, a disallowed
	 * to <code>false</code>.
	 * @since 3.0
	 */
	private Map<Object, Boolean> fAllowedAnnotationTypes= new HashMap<>();
	/**
	 * Map of allowed header annotation types.
	 * An allowed annotation type maps to <code>true</code>, a disallowed
	 * to <code>false</code>.
	 * @since 3.0
	 */
	private Map<Object, Boolean> fAllowedHeaderAnnotationTypes= new HashMap<>();
	/**
	 * The cached annotations.
	 * @since 3.0
	 */
	private List<Annotation> fCachedAnnotations= new ArrayList<>();

	/**
	 * Redraw runnable lock
	 * @since 3.3
	 */
	private Object fRunnableLock= new Object();
	/**
	 * Redraw runnable state
	 * @since 3.3
	 */
	private boolean fIsRunnablePosted= false;
	/**
	 * Redraw runnable
	 * @since 3.3
	 */
	private Runnable fRunnable= () -> {
		synchronized (fRunnableLock) {
			fIsRunnablePosted= false;
		}
		redraw();
		updateHeader();
	};
	/**
	 * Tells whether temporary annotations are drawn with
	 * a separate color. This color will be computed by
	 * discoloring the original annotation color.
	 *
	 * @since 3.4
	 */
	private boolean fIsTemporaryAnnotationDiscolored;

	/**
	 * Tells whether saturated colors are used in the overview ruler.
	 *
	 * @since 3.8
	 */
	private boolean fUseSaturatedColors= false;


	/**
	 * Constructs a overview ruler of the given width using the given annotation access and the given
	 * color manager.
	 * <p><strong>Note:</strong> As of 3.4, temporary annotations are no longer discolored.
	 * Use {@link #OverviewRuler(IAnnotationAccess, int, ISharedTextColors, boolean)} if you
	 * want to keep the old behavior.</p>
	 *
	 * @param annotationAccess the annotation access
	 * @param width the width of the vertical ruler
	 * @param sharedColors the color manager
	 */
	public OverviewRuler(IAnnotationAccess annotationAccess, int width, ISharedTextColors sharedColors) {
		this(annotationAccess, width, sharedColors, false);
	}

	/**
	 * Constructs a overview ruler of the given width using the given annotation
	 * access and the given color manager.
	 *
	 * @param annotationAccess the annotation access
	 * @param width the width of the vertical ruler
	 * @param sharedColors the color manager
	 * @param discolorTemporaryAnnotation <code>true</code> if temporary annotations should be discolored
	 * @since 3.4
	 */
	public OverviewRuler(IAnnotationAccess annotationAccess, int width, ISharedTextColors sharedColors, boolean discolorTemporaryAnnotation) {
		fAnnotationAccess= annotationAccess;
		fWidth= width;
		fSharedTextColors= sharedColors;
		fIsTemporaryAnnotationDiscolored= discolorTemporaryAnnotation;
	}

	@Override
	public Control getControl() {
		return fCanvas;
	}

	@Override
	public int getWidth() {
		return fWidth;
	}

	@Override
	public void setModel(IAnnotationModel model) {
		if (model != fModel || model != null) {

			if (fModel != null)
				fModel.removeAnnotationModelListener(fInternalListener);

			fModel= model;

			if (fModel != null)
				fModel.addAnnotationModelListener(fInternalListener);

			update();
		}
	}

	@Override
	public Control createControl(Composite parent, ITextViewer textViewer) {

		fTextViewer= textViewer;

		fHitDetectionCursor= parent.getDisplay().getSystemCursor(SWT.CURSOR_HAND);

		fHeader= new Canvas(parent, SWT.NONE);

		if (fAnnotationAccess instanceof IAnnotationAccessExtension) {
			fHeader.addMouseTrackListener(new MouseTrackAdapter() {
				/*
				 * @see org.eclipse.swt.events.MouseTrackAdapter#mouseHover(org.eclipse.swt.events.MouseEvent)
				 * @since 3.3
				 */
				@Override
				public void mouseEnter(MouseEvent e) {
					updateHeaderToolTipText();
				}
			});
		}

		fCanvas= new Canvas(parent, SWT.NO_BACKGROUND);

		fCanvas.addPaintListener(event -> {
			if (fTextViewer != null)
				doubleBufferPaint(event.gc);
		});

		fCanvas.addDisposeListener(event -> {
			handleDispose();
			fTextViewer= null;
		});

		fCanvas.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseDown(MouseEvent event) {
				handleMouseDown(event);
			}
		});

		fCanvas.addMouseMoveListener(this::handleMouseMove);

		fCanvas.addMouseWheelListener(this::handleMouseScrolled);

		if (fTextViewer != null) {
			fTextViewer.addTextListener(fInternalListener);
			// on word wrap toggle a "resized" ControlEvent is fired: suggest a redraw of the ruler
			fTextViewer.getTextWidget().addControlListener(new ControlAdapter() {
				@Override
				public void controlResized(ControlEvent e) {
					if (fTextViewer == null) {
						return;
					}
					StyledText textWidget= fTextViewer.getTextWidget();
					if (textWidget != null && textWidget.getWordWrap()) {
						redraw();
					}
				}
			});
		}

		return fCanvas;
	}

	/**
	 * Disposes the ruler's resources.
	 */
	private void handleDispose() {

		if (fTextViewer != null) {
			fTextViewer.removeTextListener(fInternalListener);
			fTextViewer= null;
		}

		if (fModel != null)
			fModel.removeAnnotationModelListener(fInternalListener);

		if (fBuffer != null) {
			fBuffer.dispose();
			fBuffer= null;
		}

		synchronized (fRunnableLock){
			fConfiguredAnnotationTypes.clear();
			fAllowedAnnotationTypes.clear();
			fConfiguredHeaderAnnotationTypes.clear();
			fAllowedHeaderAnnotationTypes.clear();
		}
		fAnnotationTypes2Colors.clear();
		fAnnotationsSortedByLayer.clear();
		fLayersSortedByLayer.clear();
	}

	/**
	 * Double buffer drawing.
	 *
	 * @param dest the GC to draw into
	 */
	private void doubleBufferPaint(GC dest) {

		Point size= fCanvas.getSize();

		if (size.x <= 0 || size.y <= 0)
			return;

		if (fBuffer != null) {
			Rectangle r= fBuffer.getBounds();
			if (r.width != size.x || r.height != size.y) {
				fBuffer.dispose();
				fBuffer= null;
			}
		}
		if (fBuffer == null)
			fBuffer= new Image(fCanvas.getDisplay(), size.x, size.y);

		GC gc= new GC(fBuffer);
		try {
			gc.setBackground(fCanvas.getBackground());
			gc.fillRectangle(0, 0, size.x, size.y);

			cacheAnnotations();

			doPaint(gc);

		} finally {
			gc.dispose();
		}

		dest.drawImage(fBuffer, 0, 0);
	}

	private void cacheAnnotations() {
		fCachedAnnotations.clear();
		if (fModel != null) {
			Iterator<Annotation> iter= fModel.getAnnotationIterator();
			while (iter.hasNext()) {
				Annotation annotation= iter.next();

				if (annotation.isMarkedDeleted())
					continue;

				if (skip(annotation.getType()))
					continue;

				fCachedAnnotations.add(annotation);
			}
		}
	}

	/**
	 * Draws this overview ruler.
	 *
	 * @param gc the GC to draw into
	 */
	private void doPaint(GC gc) {

		Rectangle r= new Rectangle(0, 0, 0, 0);
		int yy, hh= ANNOTATION_HEIGHT;

		IDocument document= fTextViewer.getDocument();
		StyledText textWidget= fTextViewer.getTextWidget();
		ITextViewerExtension5 extension= null;
		IRegion visible= null;
		if (fTextViewer instanceof ITextViewerExtension5)
			extension= (ITextViewerExtension5) fTextViewer;
		else
			visible= fTextViewer.getVisibleRegion(); // legacy support

		WidgetInfos infos= null;

		for (Object annotationType : fAnnotationsSortedByLayer) {
			if (skip(annotationType))
				continue;

			int[] style= new int[] { FilterIterator.PERSISTENT, FilterIterator.TEMPORARY };
			for (int element : style) {
				boolean areColorsComputed= false;
				Color fill= null;
				Color stroke= null;

				Iterator<Annotation> e= new FilterIterator(annotationType, element, fCachedAnnotations.iterator());
				while (e.hasNext()) {
					Annotation a= e.next();
					Position p= fModel.getPosition(a);

					if (p == null)
						continue;
					if (visible != null && !p.overlapsWith(visible.getOffset(), visible.getLength()))
						continue;

					int annotationOffset= p.getOffset();
					int annotationLength= p.getLength();
					IRegion widgetRegion= null;
					if (visible != null) {
						annotationOffset= Math.max(p.getOffset(), visible.getOffset());
						int annotationEnd= Math.min(p.getOffset() + p.getLength(), visible.getOffset() + visible.getLength());
						annotationLength= annotationEnd - annotationOffset;
					} else {
						widgetRegion= extension.modelRange2WidgetRange(new Region(annotationOffset, annotationLength));
						if (widgetRegion == null)
							continue;
					}

					if (infos == null) {
						infos= new WidgetInfos(textWidget, fCanvas);
						r.x= INSET;
						r.width= infos.bounds.width - (2 * INSET);
					}

					try {
						int startOffset= visible != null ? annotationOffset - visible.getOffset() : widgetRegion.getOffset();
						int startLine= textWidget.getLineAtOffset(startOffset);

						yy= computeY(startLine, infos);

						if (ANNOTATION_HEIGHT_SCALABLE) {
							int numberOfLines= document.getNumberOfLines(annotationOffset, annotationLength);
							// don't count empty trailing line
							IRegion lastLine= document.getLineInformationOfOffset(annotationOffset + annotationLength);
							if (lastLine.getOffset() == annotationOffset + annotationLength) {
								numberOfLines--;
							}
							if (numberOfLines > 1) {
								int yy2= computeY(startLine + numberOfLines - 1, infos);
								hh= Math.max(yy2 - yy, ANNOTATION_HEIGHT);
							} else {
								hh= ANNOTATION_HEIGHT;
							}
						}
						fAnnotationHeight= hh;

						if (!areColorsComputed) {
							stroke= getStrokeColor(annotationType, element == FilterIterator.TEMPORARY);
							fill= fUseSaturatedColors ? stroke : getFillColor(annotationType, element == FilterIterator.TEMPORARY);
							areColorsComputed= true;
						}

						if (fill != null) {
							gc.setBackground(fill);
							gc.fillRectangle(INSET, yy, infos.bounds.width-(2*INSET), hh);
						}

						if (stroke != null) {
							gc.setForeground(stroke);
							r.y= yy;
							if (yy + hh == infos.bounds.height)
								r.y--;
							r.height= hh;
							gc.setLineWidth(0); // NOTE: 0 means width is 1 but with optimized performance
							gc.drawRectangle(r);
						}
					} catch (BadLocationException | IllegalArgumentException x) {
						// We don't care if the widget's content is changed since the annotation was created
						// and do not match the annotation line/offset etc
					}
				}
			}
		}

		if (DEBUG_DRAW) {
			// draw debugging guides (boundaries):
			if (infos == null)
				infos= new WidgetInfos(textWidget, fCanvas);
			gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_DARK_MAGENTA));
			yy= infos.thumbHeight / 2;
			gc.drawLine(0, yy, infos.bounds.x/2, yy);
			yy= infos.bounds.height - infos.thumbHeight / 2;
			gc.drawLine(0, yy, infos.bounds.x/2, yy);

			gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_BLUE));
			yy= 0;
			gc.drawLine(0, yy, infos.bounds.x/2, yy);
			yy= infos.bounds.height - 1;
			gc.drawLine(0, yy, infos.bounds.x/2, yy);
		}
	}

	/**
	 * Computes and returns the y location of the given startLine.
	 *
	 * @param startLine the start line
	 * @param infos the cached widget infos
	 * @return the vertical position of the given startLine in the overview ruler
	 * @since 3.7
	 */
	private int computeY(int startLine, WidgetInfos infos) {
		// this is the inverse of #toLineNumbers(int)

		int yy;
		if (infos.bounds.height > infos.writable || infos.invisibleLines <= 0) { // too few lines for relative positions: align annotations with textWidget lines
			yy = Math.max(0, (2 * startLine + 1) * infos.writable / (infos.maxLines * 2) - infos.bounds.y);
			if (DEBUG_COMPUTE_Y)
				System.out.println("static: " + yy); //$NON-NLS-1$

		} else if (startLine + 1 < infos.visibleLines / 2) { // before middle of first page: map to area from 0 to thumbHeight/2
			yy= (int) (startLine * infos.thumbHeight / infos.visibleLines); // == startLine * (thumbHeight / 2) / (visibleLines / 2);
			if (DEBUG_COMPUTE_Y)
				System.out.println("start:  " + yy); //$NON-NLS-1$

		} else if (infos.maxLines - infos.visibleLines / 2 <= startLine) { // after middle of last page: map to area from canvasHeight-1 - thumbHeight/2 to canvasHeight-1
			yy= (int) (infos.bounds.height-1 - (double)infos.thumbHeight / 2 + (startLine - (infos.maxLines - infos.visibleLines / 2) + 1) * infos.thumbHeight / infos.visibleLines);
			if (DEBUG_COMPUTE_Y)
				System.out.println("end:    " + yy); //$NON-NLS-1$

		} else { // middle of text: map to area from thumbHeight/2 to (canvasHeight-1 - thumbHeight/2)
			yy= (int) ((double)infos.thumbHeight/2 + (startLine + 1 - infos.visibleLines / 2) * (infos.bounds.height-1 - infos.thumbHeight) / infos.invisibleLines);
			if (DEBUG_COMPUTE_Y)
				System.out.println("middle: " + yy); //$NON-NLS-1$
		}
		// center of rectangle should be at the calculated position:
		yy-= ANNOTATION_HEIGHT / 2;
		// cap at start/end:
		yy= Math.max(0, Math.min(yy, infos.bounds.height-1 - ANNOTATION_HEIGHT));
		return yy;
	}

	 @Override
	public void update() {
		if (fCanvas != null && !fCanvas.isDisposed()) {
			Display d= fCanvas.getDisplay();
			if (d != null) {
				synchronized (fRunnableLock) {
					if (fIsRunnablePosted)
						return;
					fIsRunnablePosted= true;
				}
				d.asyncExec(fRunnable);
			}
		}
	}

	/**
	 * Redraws the overview ruler.
	 */
	private void redraw() {
		if (fTextViewer == null || fModel == null)
			return;

		if (fCanvas != null && !fCanvas.isDisposed()) {
			if (VerticalRuler.AVOID_NEW_GC) {
				fCanvas.redraw();
			} else {
				GC gc= new GC(fCanvas);
				doubleBufferPaint(gc);
				gc.dispose();
			}
		}
	}

	/**
	 * Translates a given y-coordinate of this ruler into the corresponding
	 * document lines. The number of lines depends on the concrete scaling
	 * given as the ration between the height of this ruler and the length
	 * of the document.
	 *
	 * @param y_coordinate the y-coordinate
	 * @param annotationRect <code>true</code> to only consider the position of a drawn annotation rectangle,
	 * 	<code>false</code> to consider the whole line
	 * @return the corresponding document lines as {firstLine, lastLine}, or {-1, -1} if no lines correspond to the y-coordinate
	 */
	private int[] toLineNumbers(int y_coordinate, boolean annotationRect) {
		// this is the inverse of #computeY(int, WidgetInfos)

		WidgetInfos infos= new WidgetInfos(fTextViewer.getTextWidget(), fCanvas);

		if (y_coordinate >= infos.writable || y_coordinate >= infos.bounds.height || y_coordinate < 0)
			return new int[] {-1, -1};

		if (annotationRect && ANNOTATION_HEIGHT >= infos.bounds.height / infos.maxLines)
			annotationRect= false;

		int[] lines= new int[2];
		int[] pixels;

		int pixelEnd= Math.min(infos.bounds.height, y_coordinate + ANNOTATION_HEIGHT / 2 + 1);
		if (annotationRect) {
			pixels= new int[] { pixelEnd };
		} else {
			int pixelStart= Math.max(y_coordinate - ANNOTATION_HEIGHT / 2 + 1, 0);
			pixels= new int[] { pixelStart, pixelEnd };
		}

		if (infos.bounds.height > infos.writable || infos.invisibleLines <= 0) { // too few lines for relative positions: align annotations with textWidget lines
//			yy = Math.max(0, (2 * startLine + 1) * infos.writable / (infos.maxLines * 2) - infos.bounds.y);
			for (int i= 0; i < pixels.length; i++)
				lines[i]= (int) ((pixels[i] + infos.bounds.y) * infos.maxLines / (double)infos.writable);
			if (DEBUG_TO_DOCUMENT_LINE_NUMBER)
				System.out.println("static y: " + y_coordinate + " => [" + lines[0] + ", " + lines[1] + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$

		} else if (y_coordinate < infos.thumbHeight / 2) { // before middle of first page: map to area from 0 to thumbHeight/2
//			yy= (int) (startLine * infos.thumbHeight / infos.visibleLines);
			for (int i= 0; i < pixels.length; i++)
				lines[i] = (int) (pixels[i] * infos.visibleLines / infos.thumbHeight);
			if (DEBUG_TO_DOCUMENT_LINE_NUMBER)
				System.out.println("start  y: " + y_coordinate + " => [" + lines[0] + ", " + lines[1] + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$

		} else if (infos.bounds.height - 1 - infos.thumbHeight / 2 < y_coordinate) { // after middle of last page: map to area from canvasHeight-1 - thumbHeight/2 to canvasHeight-1
//			yy= (int) (infos.bounds.height-1 - (double)infos.thumbHeight / 2 + (startLine - (infos.maxLines - infos.visibleLines / 2) + 1) * infos.thumbHeight / infos.visibleLines);
			for (int i= 0; i < pixels.length; i++)
				lines[i] = (int) ((pixels[i] - (infos.bounds.height-1) + (double)infos.thumbHeight / 2) * infos.visibleLines / infos.thumbHeight - 1 + (infos.maxLines - infos.visibleLines / 2));
			if (DEBUG_TO_DOCUMENT_LINE_NUMBER)
				System.out.println("end    y: " + y_coordinate + " => [" + lines[0] + ", " + lines[1] + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$

		} else { // middle of text: map to area from thumbHeight/2 to (canvasHeight-1 - thumbHeight/2)
//			yy= (int) ((double)infos.thumbHeight/2 + (startLine + 1 - infos.visibleLines / 2) * (infos.bounds.height-1 - infos.thumbHeight) / infos.invisibleLines);
			for (int i= 0; i < pixels.length; i++)
				lines[i]= (int) ((pixels[i] - (double)infos.thumbHeight/2) * infos.invisibleLines / (infos.bounds.height-1 - infos.thumbHeight) - 1 + infos.visibleLines / 2);
			if (DEBUG_TO_DOCUMENT_LINE_NUMBER)
				System.out.println("middle y: " + y_coordinate + " => [" + lines[0] + ", " + lines[1] + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		}

		if (y_coordinate < ANNOTATION_HEIGHT && y_coordinate < infos.bounds.y)
			lines[0]= 0;
		else if (lines[0] < 0)
			lines[0]= 0;

		if (annotationRect) {
			int y0= computeY(lines[0], infos);
			if (y_coordinate < y0 || y0 + ANNOTATION_HEIGHT < y_coordinate) {
				lines[0]= -1;
				lines[1]= -1;
				return lines;
			} else {
				lines[1]= lines[0];
			}
		}

		if (lines[1] > infos.maxLines)
			lines[1]= infos.maxLines;

		if (fTextViewer instanceof ITextViewerExtension5) {
			ITextViewerExtension5 extension= (ITextViewerExtension5) fTextViewer;
			lines[0]= extension.widgetLine2ModelLine(lines[0]);
			lines[1]= extension.widgetLine2ModelLine(lines[1]);
		} else {
			try {
				IRegion visible= fTextViewer.getVisibleRegion();
				int lineNumber= fTextViewer.getDocument().getLineOfOffset(visible.getOffset());
				lines[0] += lineNumber;
				lines[1] += lineNumber;
			} catch (BadLocationException x) {
			}
		}

		if (DEBUG_TO_DOCUMENT_LINE_NUMBER)
			System.out.println("result: [" + lines[0] + ", " + lines[1] + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		return lines;
	}

	/**
	 * Returns the position of the first annotation found in the given line range.
	 *
	 * @param lineNumbers the line range
	 * @return the position of the first found annotation
	 */
	private Position getAnnotationPosition(int[] lineNumbers) {
		if (lineNumbers[0] == -1)
			return null;

		Position found= null;

		try {
			IDocument d= fTextViewer.getDocument();
			IRegion line= d.getLineInformation(lineNumbers[0]);

			int start= line.getOffset();

			line= d.getLineInformation(lineNumbers[lineNumbers.length - 1]);
			int end= line.getOffset() + line.getLength();

			for (int i= fAnnotationsSortedByLayer.size() -1; i >= 0; i--) {

				Object annotationType= fAnnotationsSortedByLayer.get(i);

				Iterator<Annotation> e= new FilterIterator(annotationType, FilterIterator.PERSISTENT | FilterIterator.TEMPORARY);
				while (e.hasNext() && found == null) {
					Annotation a= e.next();
					if (a.isMarkedDeleted())
						continue;

					if (skip(a.getType()))
						continue;

					Position p= fModel.getPosition(a);
					if (p == null)
						continue;

					int posOffset= p.getOffset();
					int posEnd= posOffset + p.getLength();
					IRegion region= d.getLineInformationOfOffset(posEnd);
					// trailing empty lines don't count
					if (posEnd > posOffset && region.getOffset() == posEnd) {
						posEnd--;
						region= d.getLineInformationOfOffset(posEnd);
					}

					if (posOffset <= end && posEnd >= start)
							found= p;
				}
			}
		} catch (BadLocationException x) {
		}

		return found;
	}

	/**
	 * Returns the line which  corresponds best to one of
	 * the underlying annotations at the given y-coordinate.
	 *
	 * @param lineNumbers the line numbers
	 * @return the best matching line or <code>-1</code> if no such line can be found
	 */
	private int findBestMatchingLineNumber(int[] lineNumbers) {
		if (lineNumbers == null || lineNumbers.length < 1)
			return -1;

		try {
			Position pos= getAnnotationPosition(lineNumbers);
			if (pos == null)
				return -1;
			return fTextViewer.getDocument().getLineOfOffset(pos.getOffset());
		} catch (BadLocationException ex) {
			return -1;
		}
	}

	/**
	 * Handles mouse clicks.
	 *
	 * @param event the mouse button down event
	 */
	private void handleMouseDown(MouseEvent event) {
		if (fTextViewer != null) {
			int[] lines= toLineNumbers(event.y, true);
			if (lines[0] == -1)
				lines= toLineNumbers(event.y, false);
			Position p= getAnnotationPosition(lines);
			if (p == null && event.button == 1) {
				try {
					p= new Position(fTextViewer.getDocument().getLineInformation(lines[0]).getOffset(), 0);
				} catch (BadLocationException e) {
					// do nothing
				}
			}
			if (p != null) {
				fTextViewer.revealRange(p.getOffset(), p.getLength());
				fTextViewer.setSelectedRange(p.getOffset(), p.getLength());
			}
			fTextViewer.getTextWidget().setFocus();
		}
		fLastMouseButtonActivityLine= toDocumentLineNumber(event.y);
	}

	/**
	 * Handles mouse moves.
	 *
	 * @param event the mouse move event
	 */
	private void handleMouseMove(MouseEvent event) {
		if (fTextViewer != null) {
			int[] lines= toLineNumbers(event.y, true);
			Position p= getAnnotationPosition(lines);
			Cursor cursor= (p != null ? fHitDetectionCursor : null);
			if (cursor != fLastCursor) {
				fCanvas.setCursor(cursor);
				fLastCursor= cursor;
			}
		}
	}

	/**
	 * Handles mouse scrolls.
	 *
	 * @param event the mouse scrolled event
	 */
	private void handleMouseScrolled(MouseEvent event) {
		if (fTextViewer instanceof ITextViewerExtension5) {
			ITextViewerExtension5 extension= (ITextViewerExtension5) fTextViewer;
			StyledText textWidget= fTextViewer.getTextWidget();
			int topIndex= textWidget.getTopIndex();
			int newTopIndex= Math.max(0, topIndex - event.count);
			fTextViewer.setTopIndex(extension.widgetLine2ModelLine(newTopIndex));
		} else if (fTextViewer != null) {
			int topIndex= fTextViewer.getTopIndex();
			int newTopIndex= Math.max(0, topIndex - event.count);
			fTextViewer.setTopIndex(newTopIndex);
		}
	}

	@Override
	public void addAnnotationType(Object annotationType) {
		synchronized (fRunnableLock){
			fConfiguredAnnotationTypes.add(annotationType);
			fAllowedAnnotationTypes.clear();
		}
	}

	@Override
	public void removeAnnotationType(Object annotationType) {
		synchronized (fRunnableLock){
			fConfiguredAnnotationTypes.remove(annotationType);
			fAllowedAnnotationTypes.clear();
		}
	}

	@Override
	public void setAnnotationTypeLayer(Object annotationType, int layer) {
		int j= fAnnotationsSortedByLayer.indexOf(annotationType);
		if (j != -1) {
			fAnnotationsSortedByLayer.remove(j);
			fLayersSortedByLayer.remove(j);
		}

		if (layer >= 0) {
			int i= 0;
			int size= fLayersSortedByLayer.size();
			while (i < size && layer >= fLayersSortedByLayer.get(i).intValue())
				i++;
			Integer layerObj= Integer.valueOf(layer);
			fLayersSortedByLayer.add(i, layerObj);
			fAnnotationsSortedByLayer.add(i, annotationType);
		}
	}

	@Override
	public void setAnnotationTypeColor(Object annotationType, Color color) {
		if (color != null)
			fAnnotationTypes2Colors.put(annotationType, color);
		else
			fAnnotationTypes2Colors.remove(annotationType);
	}

	/**
	 * Returns whether the given annotation type should be skipped by the drawing routine.
	 *
	 * @param annotationType the annotation type
	 * @return <code>true</code> if annotation of the given type should be skipped
	 */
	private boolean skip(Object annotationType) {
		return !contains(annotationType, fAllowedAnnotationTypes, fConfiguredAnnotationTypes);
	}

	/**
	 * Returns whether the given annotation type should be skipped by the drawing routine of the header.
	 *
	 * @param annotationType the annotation type
	 * @return <code>true</code> if annotation of the given type should be skipped
	 * @since 3.0
	 */
	private boolean skipInHeader(Object annotationType) {
		return !contains(annotationType, fAllowedHeaderAnnotationTypes, fConfiguredHeaderAnnotationTypes);
	}

	/**
	 * Returns whether the given annotation type is mapped to <code>true</code>
	 * in the given <code>allowed</code> map or covered by the <code>configured</code>
	 * set.
	 *
	 * @param annotationType the annotation type
	 * @param allowed the map with allowed annotation types mapped to booleans
	 * @param configured the set with configured annotation types
	 * @return <code>true</code> if annotation is contained, <code>false</code>
	 *         otherwise
	 * @since 3.0
	 */
	private boolean contains(Object annotationType, Map<Object, Boolean> allowed, Set<Object> configured) {
		boolean covered;
		synchronized (fRunnableLock){
			Boolean cached= allowed.get(annotationType);
			if (cached != null)
				return cached.booleanValue();

			covered = isCovered(annotationType, configured);
			allowed.put(annotationType, covered ? Boolean.TRUE : Boolean.FALSE);
		}
		return covered;
	}

	/**
	 * Computes whether the annotations of the given type are covered by the given <code>configured</code>
	 * set. This is the case if either the type of the annotation or any of its
	 * super types is contained in the <code>configured</code> set.
	 *
	 * @param annotationType the annotation type
	 * @param configured the set with configured annotation types
	 * @return <code>true</code> if annotation is covered, <code>false</code>
	 *         otherwise
	 * @since 3.0
	 */
	private boolean isCovered(Object annotationType, Set<Object> configured) {
		if (fAnnotationAccess instanceof IAnnotationAccessExtension) {
			IAnnotationAccessExtension extension= (IAnnotationAccessExtension) fAnnotationAccess;
			Iterator<Object> e= configured.iterator();
			while (e.hasNext()) {
				if (extension.isSubtype(annotationType,e.next()))
					return true;
			}
			return false;
		}
		return configured.contains(annotationType);
	}

	/**
	 * Returns a specification of a color that lies between the given
	 * foreground and background color using the given scale factor.
	 *
	 * @param fg the foreground color
	 * @param bg the background color
	 * @param scale the scale factor
	 * @return the interpolated color
	 */
	private static RGB interpolate(RGB fg, RGB bg, double scale) {
		return new RGB(
			(int) ((1.0-scale) * fg.red + scale * bg.red),
			(int) ((1.0-scale) * fg.green + scale * bg.green),
			(int) ((1.0-scale) * fg.blue + scale * bg.blue)
		);
	}

	/**
	 * Returns the grey value in which the given color would be drawn in grey-scale.
	 *
	 * @param rgb the color
	 * @return the grey-scale value
	 */
	private static double greyLevel(RGB rgb) {
		if (rgb.red == rgb.green && rgb.green == rgb.blue)
			return rgb.red;
		return  (0.299 * rgb.red + 0.587 * rgb.green + 0.114 * rgb.blue + 0.5);
	}

	/**
	 * Returns whether the given color is dark or light depending on the colors grey-scale level.
	 *
	 * @param rgb the color
	 * @return <code>true</code> if the color is dark, <code>false</code> if it is light
	 */
	private static boolean isDark(RGB rgb) {
		return greyLevel(rgb) > 128;
	}

	/**
	 * Returns a color based on the color configured for the given annotation type and the given scale factor.
	 *
	 * @param annotationType the annotation type
	 * @param scale the scale factor
	 * @return the computed color
	 */
	private Color getColor(Object annotationType, double scale) {
		Color base= findColor(annotationType);
		if (base == null)
			return null;

		RGB baseRGB= base.getRGB();
		RGB background= fCanvas.getBackground().getRGB();

		boolean darkBase= isDark(baseRGB);
		boolean darkBackground= isDark(background);
		if (darkBase && darkBackground)
			background= new RGB(255, 255, 255);
		else if (!darkBase && !darkBackground)
			background= new RGB(0, 0, 0);

		return fSharedTextColors.getColor(interpolate(baseRGB, background, scale));
	}

	/**
	 * Returns the color for the given annotation type
	 *
	 * @param annotationType the annotation type
	 * @return the color
	 * @since 3.0
	 */
	private Color findColor(Object annotationType) {
		Color color= fAnnotationTypes2Colors.get(annotationType);
		if (color != null)
			return color;

		if (fAnnotationAccess instanceof IAnnotationAccessExtension) {
			IAnnotationAccessExtension extension= (IAnnotationAccessExtension) fAnnotationAccess;
			Object[] superTypes= extension.getSupertypes(annotationType);
			if (superTypes != null) {
				for (Object superType : superTypes) {
					color= fAnnotationTypes2Colors.get(superType);
					if (color != null)
						return color;
				}
			}
		}

		return null;
	}

	/**
	 * Returns the stroke color for the given annotation type and characteristics.
	 *
	 * @param annotationType the annotation type
	 * @param temporary <code>true</code> if for temporary annotations
	 * @return the stroke color
	 */
	private Color getStrokeColor(Object annotationType, boolean temporary) {
		return getColor(annotationType, temporary && fIsTemporaryAnnotationDiscolored ? 0.5 : 0.2);
	}

	/**
	 * Returns the fill color for the given annotation type and characteristics.
	 *
	 * @param annotationType the annotation type
	 * @param temporary <code>true</code> if for temporary annotations
	 * @return the fill color
	 */
	private Color getFillColor(Object annotationType, boolean temporary) {
		return getColor(annotationType, temporary && fIsTemporaryAnnotationDiscolored ? 0.9 : 0.75);
	}

	@Override
	public int getLineOfLastMouseButtonActivity() {
		if (fLastMouseButtonActivityLine >= fTextViewer.getDocument().getNumberOfLines())
			fLastMouseButtonActivityLine= -1;
		return fLastMouseButtonActivityLine;
	}

	@Override
	public int toDocumentLineNumber(int y_coordinate) {

		if (fTextViewer == null || y_coordinate == -1)
			return -1;

		int[] lineNumbers= toLineNumbers(y_coordinate, true);
		if (lineNumbers[0] == -1)
			lineNumbers= toLineNumbers(y_coordinate, false);
		int bestLine= findBestMatchingLineNumber(lineNumbers);
		if (bestLine == -1 && lineNumbers.length > 0)
			return lineNumbers[0];
		return	bestLine;
	}

	@Override
	public IAnnotationModel getModel() {
		return fModel;
	}

	@Override
	public int getAnnotationHeight() {
		return fAnnotationHeight;
	}

	@Override
	public boolean hasAnnotation(int y) {
		return findBestMatchingLineNumber(toLineNumbers(y, true)) != -1;
	}

	@Override
	public Control getHeaderControl() {
		return fHeader;
	}

	@Override
	public void addHeaderAnnotationType(Object annotationType) {
		synchronized (fRunnableLock) {
			fConfiguredHeaderAnnotationTypes.add(annotationType);
			fAllowedHeaderAnnotationTypes.clear();
		}
	}

	@Override
	public void removeHeaderAnnotationType(Object annotationType) {
		synchronized (fRunnableLock) {
			fConfiguredHeaderAnnotationTypes.remove(annotationType);
			fAllowedHeaderAnnotationTypes.clear();
		}
	}

	/**
	 * Updates the header of this ruler.
	 */
	private void updateHeader() {
		if (fHeader == null || fHeader.isDisposed())
			return;

		fHeader.setToolTipText(null);

		Object colorType= null;
		outer: for (int i= fAnnotationsSortedByLayer.size() -1; i >= 0; i--) {
			Object annotationType= fAnnotationsSortedByLayer.get(i);
			if (skipInHeader(annotationType) || skip(annotationType))
				continue;

			Iterator<Annotation> e= new FilterIterator(annotationType, FilterIterator.PERSISTENT | FilterIterator.TEMPORARY | FilterIterator.IGNORE_BAGS, fCachedAnnotations.iterator());
			while (e.hasNext()) {
				if (e.next() != null) {
					colorType= annotationType;
					break outer;
				}
			}
		}

		Color color= null;
		if (colorType != null)
			color= findColor(colorType);

		if (color == null) {
			if (fHeaderPainter != null)
				fHeaderPainter.setColor(null);
		}	else {
			if (fHeaderPainter == null) {
				fHeaderPainter= new HeaderPainter();
				fHeader.addPaintListener(fHeaderPainter);
			}
			fHeaderPainter.setColor(color);
		}

		fHeader.redraw();

	}

	/**
	 * Updates the header tool tip text of this ruler.
	 */
	private void updateHeaderToolTipText() {
		if (fHeader == null || fHeader.isDisposed())
			return;

		if (fHeader.getToolTipText() != null)
			return;

		StringBuilder overview = new StringBuilder();

		for (int i= fAnnotationsSortedByLayer.size() -1; i >= 0; i--) {

			Object annotationType= fAnnotationsSortedByLayer.get(i);

			if (skipInHeader(annotationType) || skip(annotationType))
				continue;

			int count= 0;
			String annotationTypeLabel= null;

			Iterator<Annotation> e= new FilterIterator(annotationType, FilterIterator.PERSISTENT | FilterIterator.TEMPORARY | FilterIterator.IGNORE_BAGS, fCachedAnnotations.iterator());
			while (e.hasNext()) {
				Annotation annotation= e.next();
				if (annotation != null) {
					if (annotationTypeLabel == null)
						annotationTypeLabel= ((IAnnotationAccessExtension)fAnnotationAccess).getTypeLabel(annotation);
					count++;
				}
			}

			if (annotationTypeLabel != null) {
				if (overview.length() > 0) {
					overview.append("\n"); //$NON-NLS-1$
				}
				overview.append(JFaceTextMessages.getFormattedString("OverviewRulerHeader.toolTipTextEntry", annotationTypeLabel, Integer.valueOf(count))); //$NON-NLS-1$
			}
		}

		if (overview.length() > 0)
			fHeader.setToolTipText(overview.toString());
	}

	/**
	 * {@inheritDoc}
	 *
	 * @since 3.8
	 */
	@Override
	public void setUseSaturatedColors(boolean useSaturatedColor) {
		fUseSaturatedColors= useSaturatedColor;
	}
}
