Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*******************************************************************************
* Copyright (c) 2000, 2016 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.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.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.MouseWheelListener;
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.
*
* Clients usually instantiate and configure objects of this class.
*
*
* @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 {
final static int TEMPORARY= 1 << 1;
final static int PERSISTENT= 1 << 2;
final static int IGNORE_BAGS= 1 << 3;
private Iterator 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 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
*/
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)
*/
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();
writable= JFaceTextUtil.computeLineHeight(textWidget, 0, maxLines, maxLines);
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