mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-08 16:55:38 +02:00
Add overview ruler and line numbers
This commit is contained in:
parent
c287f57cc2
commit
324f4bf5dd
2 changed files with 706 additions and 15 deletions
|
@ -44,9 +44,13 @@ import org.eclipse.jface.text.ITextSelection;
|
|||
import org.eclipse.jface.text.ITextViewerExtension;
|
||||
import org.eclipse.jface.text.Position;
|
||||
import org.eclipse.jface.text.source.Annotation;
|
||||
import org.eclipse.jface.text.source.AnnotationRulerColumn;
|
||||
import org.eclipse.jface.text.source.CompositeRuler;
|
||||
import org.eclipse.jface.text.source.IAnnotationModel;
|
||||
import org.eclipse.jface.text.source.ISourceViewer;
|
||||
import org.eclipse.jface.text.source.IVerticalRuler;
|
||||
import org.eclipse.jface.text.source.IVerticalRulerColumn;
|
||||
import org.eclipse.jface.text.source.LineNumberRulerColumn;
|
||||
import org.eclipse.jface.text.source.SourceViewer;
|
||||
import org.eclipse.jface.text.source.SourceViewerConfiguration;
|
||||
import org.eclipse.jface.util.PropertyChangeEvent;
|
||||
|
@ -56,6 +60,7 @@ import org.eclipse.jface.viewers.ISelectionProvider;
|
|||
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||
import org.eclipse.jface.viewers.SelectionChangedEvent;
|
||||
import org.eclipse.jface.viewers.StructuredSelection;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.custom.ST;
|
||||
import org.eclipse.swt.custom.StyledText;
|
||||
import org.eclipse.swt.custom.VerifyKeyListener;
|
||||
|
@ -67,10 +72,13 @@ import org.eclipse.swt.events.VerifyEvent;
|
|||
import org.eclipse.swt.events.VerifyListener;
|
||||
import org.eclipse.swt.graphics.Color;
|
||||
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.Composite;
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.Layout;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.ui.IEditorActionBarContributor;
|
||||
import org.eclipse.ui.IEditorInput;
|
||||
|
@ -102,6 +110,7 @@ import org.eclipse.cdt.internal.ui.CPlugin;
|
|||
import org.eclipse.cdt.internal.ui.IContextMenuConstants;
|
||||
import org.eclipse.cdt.internal.ui.text.CSourceViewerConfiguration;
|
||||
import org.eclipse.cdt.internal.ui.text.CTextTools;
|
||||
import org.eclipse.cdt.internal.ui.text.IColorManager;
|
||||
import org.eclipse.cdt.ui.ICDTConstants;
|
||||
import org.eclipse.cdt.ui.ICEditorContextMenuAction;
|
||||
import org.eclipse.cdt.ui.ICEditorRulerAction;
|
||||
|
@ -147,6 +156,9 @@ public class CEditor extends AbstractTextEditor implements ISelectionChangedList
|
|||
|
||||
/** Listener to annotation model changes that updates the error tick in the tab image */
|
||||
private CEditorErrorTickUpdater fCEditorErrorTickUpdater;
|
||||
|
||||
/** The line number ruler column */
|
||||
private LineNumberRulerColumn fLineNumberRulerColumn;
|
||||
|
||||
|
||||
/* Preference key line color shading */
|
||||
|
@ -181,6 +193,14 @@ public class CEditor extends AbstractTextEditor implements ISelectionChangedList
|
|||
public final static String SPACES_FOR_TABS= "spacesForTabs";
|
||||
/** Preference key for linked position color */
|
||||
public final static String LINKED_POSITION_COLOR= "linkedPositionColor"; //$NON-NLS-1$
|
||||
/** Preference key for shwoing the overview ruler */
|
||||
public final static String OVERVIEW_RULER= "overviewRuler"; //$NON-NLS-1$
|
||||
|
||||
/** Preference key for showing the line number ruler */
|
||||
public final static String LINE_NUMBER_RULER= "lineNumberRuler"; //$NON-NLS-1$
|
||||
/** Preference key for the foreground color of the line numbers */
|
||||
public final static String LINE_NUMBER_COLOR= "lineNumberColor"; //$NON-NLS-1$
|
||||
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
|
@ -459,6 +479,29 @@ public class CEditor extends AbstractTextEditor implements ISelectionChangedList
|
|||
setBracketHighlightingStyle();
|
||||
return;
|
||||
}
|
||||
if (LINE_NUMBER_RULER.equals(property)) {
|
||||
if (isLineNumberRulerVisible())
|
||||
showLineNumberRuler();
|
||||
else
|
||||
hideLineNumberRuler();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fLineNumberRulerColumn != null &&
|
||||
(LINE_NUMBER_COLOR.equals(property) ||
|
||||
PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property) ||
|
||||
PREFERENCE_COLOR_BACKGROUND.equals(property))) {
|
||||
|
||||
initializeLineNumberRulerColumn(fLineNumberRulerColumn);
|
||||
}
|
||||
|
||||
if (OVERVIEW_RULER.equals(property)) {
|
||||
if (isOverviewRulerVisible())
|
||||
showOverviewRuler();
|
||||
else
|
||||
hideOverviewRuler();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
||||
|
@ -1170,6 +1213,54 @@ public class CEditor extends AbstractTextEditor implements ISelectionChangedList
|
|||
public final static String LANGUAGE_CPP= "CEditor.language.cpp";
|
||||
public final static String LANGUAGE_C= "CEditor.language.c";
|
||||
|
||||
|
||||
class AdaptedRulerLayout extends Layout {
|
||||
|
||||
protected int fGap;
|
||||
protected AdaptedSourceViewer fAdaptedSourceViewer;
|
||||
|
||||
|
||||
protected AdaptedRulerLayout(int gap, AdaptedSourceViewer asv) {
|
||||
fGap= gap;
|
||||
fAdaptedSourceViewer= asv;
|
||||
}
|
||||
|
||||
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
|
||||
Control[] children= composite.getChildren();
|
||||
Point s= children[children.length - 1].computeSize(SWT.DEFAULT, SWT.DEFAULT, flushCache);
|
||||
if (fAdaptedSourceViewer.isVerticalRulerVisible())
|
||||
s.x += fAdaptedSourceViewer.getVerticalRuler().getWidth() + fGap;
|
||||
return s;
|
||||
}
|
||||
|
||||
protected void layout(Composite composite, boolean flushCache) {
|
||||
Rectangle clArea= composite.getClientArea();
|
||||
if (fAdaptedSourceViewer.isVerticalRulerVisible()) {
|
||||
|
||||
StyledText textWidget= fAdaptedSourceViewer.getTextWidget();
|
||||
Rectangle trim= textWidget.computeTrim(0, 0, 0, 0);
|
||||
int scrollbarHeight= trim.height;
|
||||
|
||||
IVerticalRuler vr= fAdaptedSourceViewer.getVerticalRuler();
|
||||
int vrWidth=vr.getWidth();
|
||||
|
||||
int orWidth= 0;
|
||||
if (fAdaptedSourceViewer.isOverviewRulerVisible()) {
|
||||
OverviewRuler or= fAdaptedSourceViewer.getOverviewRuler();
|
||||
orWidth= or.getWidth();
|
||||
or.getControl().setBounds(clArea.width - orWidth, scrollbarHeight, orWidth, clArea.height - 3*scrollbarHeight);
|
||||
}
|
||||
|
||||
textWidget.setBounds(vrWidth + fGap, 0, clArea.width - vrWidth - orWidth - 2*fGap, clArea.height);
|
||||
vr.getControl().setBounds(0, 0, vrWidth, clArea.height - scrollbarHeight);
|
||||
|
||||
} else {
|
||||
StyledText textWidget= fAdaptedSourceViewer.getTextWidget();
|
||||
textWidget.setBounds(0, 0, clArea.width, clArea.height);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Adapted source viewer for CEditor
|
||||
*/
|
||||
|
@ -1178,31 +1269,31 @@ public class CEditor extends AbstractTextEditor implements ISelectionChangedList
|
|||
|
||||
private List fTextConverters;
|
||||
private String fDisplayLanguage;
|
||||
//private OverviewRuler fOverviewRuler;
|
||||
//private boolean fIsOverviewRulerVisible;
|
||||
private OverviewRuler fOverviewRuler;
|
||||
private boolean fIsOverviewRulerVisible;
|
||||
|
||||
//private IVerticalRuler fCachedVerticalRuler;
|
||||
//private boolean fCachedIsVerticalRulerVisible;
|
||||
private IVerticalRuler fCachedVerticalRuler;
|
||||
private boolean fCachedIsVerticalRulerVisible;
|
||||
|
||||
|
||||
public AdaptedSourceViewer(Composite parent, IVerticalRuler ruler, int styles, String language) {
|
||||
super(parent, ruler, styles);
|
||||
|
||||
fDisplayLanguage = language;
|
||||
//fCachedVerticalRuler= ruler;
|
||||
//fCachedIsVerticalRulerVisible= (ruler != null);
|
||||
//fOverviewRuler= new OverviewRuler(VERTICAL_RULER_WIDTH);
|
||||
fCachedVerticalRuler= ruler;
|
||||
fCachedIsVerticalRulerVisible= (ruler != null);
|
||||
fOverviewRuler= new OverviewRuler(VERTICAL_RULER_WIDTH);
|
||||
|
||||
//delayedCreateControl(parent, styles);
|
||||
delayedCreateControl(parent, styles);
|
||||
}
|
||||
|
||||
/*
|
||||
* @see ISourceViewer#showAnnotations(boolean)
|
||||
*
|
||||
*/
|
||||
public void showAnnotations(boolean show) {
|
||||
fCachedIsVerticalRulerVisible= (show && fCachedVerticalRuler != null);
|
||||
super.showAnnotations(show);
|
||||
} */
|
||||
}
|
||||
/*
|
||||
public IContentAssistant getContentAssistant() {
|
||||
return fContentAssistant;
|
||||
|
@ -1268,7 +1359,6 @@ public class CEditor extends AbstractTextEditor implements ISelectionChangedList
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public IVerticalRuler getVerticalRuler() {
|
||||
return fCachedVerticalRuler;
|
||||
}
|
||||
|
@ -1283,7 +1373,7 @@ public class CEditor extends AbstractTextEditor implements ISelectionChangedList
|
|||
|
||||
/*
|
||||
* @see TextViewer#createControl(Composite, int)
|
||||
*
|
||||
*/
|
||||
protected void createControl(Composite parent, int styles) {
|
||||
// do nothing here
|
||||
}
|
||||
|
@ -1320,15 +1410,15 @@ public class CEditor extends AbstractTextEditor implements ISelectionChangedList
|
|||
|
||||
public boolean isOverviewRulerVisible() {
|
||||
return fIsOverviewRulerVisible;
|
||||
} */
|
||||
}
|
||||
|
||||
/*
|
||||
* @see ISourceViewer#setDocument(IDocument, IAnnotationModel, int, int)
|
||||
*
|
||||
*/
|
||||
public void setDocument(IDocument document, IAnnotationModel annotationModel, int visibleRegionOffset, int visibleRegionLength) {
|
||||
super.setDocument(document, annotationModel, visibleRegionOffset, visibleRegionLength);
|
||||
fOverviewRuler.setModel(annotationModel);
|
||||
} */
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the current presentation by sending an initialization
|
||||
|
@ -1639,4 +1729,107 @@ public class CEditor extends AbstractTextEditor implements ISelectionChangedList
|
|||
}
|
||||
return (ICEditorRulerAction[])rulerActions.toArray( new ICEditorRulerAction[0] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new line number ruler column that is appropriately initialized.
|
||||
*/
|
||||
protected IVerticalRulerColumn createLineNumberRulerColumn() {
|
||||
fLineNumberRulerColumn= new LineNumberRulerColumn();
|
||||
initializeLineNumberRulerColumn(fLineNumberRulerColumn);
|
||||
return fLineNumberRulerColumn;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see AbstractTextEditor#createVerticalRuler()
|
||||
*/
|
||||
protected IVerticalRuler createVerticalRuler() {
|
||||
CompositeRuler ruler= new CompositeRuler();
|
||||
ruler.addDecorator(0, new AnnotationRulerColumn(VERTICAL_RULER_WIDTH));
|
||||
if (isLineNumberRulerVisible())
|
||||
ruler.addDecorator(1, createLineNumberRulerColumn());
|
||||
return ruler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the given line number ruler column from the preference store.
|
||||
* @param rulerColumn the ruler column to be initialized
|
||||
*/
|
||||
protected void initializeLineNumberRulerColumn(LineNumberRulerColumn rulerColumn) {
|
||||
CTextTools textTools= CPlugin.getDefault().getTextTools();
|
||||
IColorManager manager= textTools.getColorManager();
|
||||
|
||||
IPreferenceStore store= getPreferenceStore();
|
||||
if (store != null) {
|
||||
|
||||
RGB rgb= null;
|
||||
// foreground color
|
||||
if (store.contains(LINE_NUMBER_COLOR)) {
|
||||
if (store.isDefault(LINE_NUMBER_COLOR))
|
||||
rgb= PreferenceConverter.getDefaultColor(store, LINE_NUMBER_COLOR);
|
||||
else
|
||||
rgb= PreferenceConverter.getColor(store, LINE_NUMBER_COLOR);
|
||||
}
|
||||
rulerColumn.setForeground(manager.getColor(rgb));
|
||||
|
||||
|
||||
rgb= null;
|
||||
// background color
|
||||
if (!store.getBoolean(PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
|
||||
if (store.contains(PREFERENCE_COLOR_BACKGROUND)) {
|
||||
if (store.isDefault(PREFERENCE_COLOR_BACKGROUND))
|
||||
rgb= PreferenceConverter.getDefaultColor(store, PREFERENCE_COLOR_BACKGROUND);
|
||||
else
|
||||
rgb= PreferenceConverter.getColor(store, PREFERENCE_COLOR_BACKGROUND);
|
||||
}
|
||||
}
|
||||
rulerColumn.setBackground(manager.getColor(rgb));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the line number ruler column.
|
||||
*/
|
||||
private void showLineNumberRuler() {
|
||||
IVerticalRuler v= getVerticalRuler();
|
||||
if (v instanceof CompositeRuler) {
|
||||
CompositeRuler c= (CompositeRuler) v;
|
||||
c.addDecorator(1, createLineNumberRulerColumn());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides the line number ruler column.
|
||||
*/
|
||||
private void hideLineNumberRuler() {
|
||||
IVerticalRuler v= getVerticalRuler();
|
||||
if (v instanceof CompositeRuler) {
|
||||
CompositeRuler c= (CompositeRuler) v;
|
||||
c.removeDecorator(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the line number ruler column should be
|
||||
* visible according to the preference store settings.
|
||||
* @return <code>true</code> if the line numbers should be visible
|
||||
*/
|
||||
private boolean isLineNumberRulerVisible() {
|
||||
IPreferenceStore store= getPreferenceStore();
|
||||
return store.getBoolean(LINE_NUMBER_RULER);
|
||||
}
|
||||
|
||||
private void showOverviewRuler() {
|
||||
AdaptedSourceViewer asv= (AdaptedSourceViewer) getSourceViewer();
|
||||
asv.showOverviewRuler();
|
||||
}
|
||||
|
||||
private void hideOverviewRuler() {
|
||||
AdaptedSourceViewer asv= (AdaptedSourceViewer) getSourceViewer();
|
||||
asv.hideOverviewRuler();
|
||||
}
|
||||
|
||||
private boolean isOverviewRulerVisible() {
|
||||
IPreferenceStore store= getPreferenceStore();
|
||||
return store.getBoolean(OVERVIEW_RULER);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,498 @@
|
|||
package org.eclipse.cdt.internal.ui.editor;
|
||||
|
||||
/*
|
||||
* (c) Copyright IBM Corp. 2000, 2001.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.custom.StyledText;
|
||||
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.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.cdt.internal.ui.CPlugin;
|
||||
import org.eclipse.cdt.internal.ui.text.CTextTools;
|
||||
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.Position;
|
||||
import org.eclipse.jface.text.TextEvent;
|
||||
import org.eclipse.jface.text.source.Annotation;
|
||||
import org.eclipse.jface.text.source.IAnnotationModel;
|
||||
import org.eclipse.jface.text.source.IAnnotationModelListener;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class OverviewRuler {
|
||||
|
||||
/**
|
||||
* Internal listener class.
|
||||
*/
|
||||
class InternalListener implements ITextListener, IAnnotationModelListener {
|
||||
|
||||
/*
|
||||
* @see ITextListener#textChanged
|
||||
*/
|
||||
public void textChanged(TextEvent e) {
|
||||
if (fTextViewer != null && e.getDocumentEvent() == null && e.getViewerRedrawState()) {
|
||||
// handle only changes of visible document
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @see IAnnotationModelListener#modelChanged(IAnnotationModel)
|
||||
*/
|
||||
public void modelChanged(IAnnotationModel model) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters problems based on their types.
|
||||
*/
|
||||
class FilterIterator implements Iterator {
|
||||
|
||||
private Iterator fIterator;
|
||||
private int fType;
|
||||
private Annotation fNext;
|
||||
|
||||
public FilterIterator(int type) {
|
||||
fType= type;
|
||||
if (fModel != null) {
|
||||
fIterator= fModel.getAnnotationIterator();
|
||||
skip();
|
||||
}
|
||||
}
|
||||
|
||||
private void skip() {
|
||||
while (fIterator.hasNext()) {
|
||||
fNext= (Annotation) fIterator.next();
|
||||
int type= getType(fNext);
|
||||
if ((fType == ALL && type != UNKNOWN) || fType == type)
|
||||
return;
|
||||
}
|
||||
fNext= null;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see Iterator#hasNext()
|
||||
*/
|
||||
public boolean hasNext() {
|
||||
return fNext != null;
|
||||
}
|
||||
/*
|
||||
* @see Iterator#next()
|
||||
*/
|
||||
public Object next() {
|
||||
try {
|
||||
return fNext;
|
||||
} finally {
|
||||
if (fModel != null)
|
||||
skip();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* @see Iterator#remove()
|
||||
*/
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** Problem types */
|
||||
private static final int ALL= -1;
|
||||
private static final int COMPILE_WARNING= 0;
|
||||
private static final int COMPILE_ERROR= 1;
|
||||
private static final int TEMPORARY= 2;
|
||||
private static final int UNKNOWN= 4;
|
||||
|
||||
/** Color table */
|
||||
private static final RGB[][] COLORS= new RGB[][] {
|
||||
/* fill */ /* stroke */
|
||||
/* warning */ { new RGB(248, 218, 114), new RGB(139, 109, 7) },
|
||||
/* error */ { new RGB(255, 140, 140), new RGB(255, 0 ,0) },
|
||||
/* temp */ { new RGB(240, 230, 230), new RGB(200, 100, 100) }
|
||||
};
|
||||
|
||||
/** drawing layers */
|
||||
private static final int[] LAYERS= new int[] { COMPILE_WARNING, TEMPORARY, COMPILE_ERROR };
|
||||
|
||||
private static final int INSET= 2;
|
||||
private static final int PROBLEM_HEIGHT_MIN= 4;
|
||||
private static boolean PROBLEM_HEIGHT_SCALABLE= false;
|
||||
|
||||
|
||||
|
||||
/** 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 drawable 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 */
|
||||
private Cursor fHitDetectionCursor;
|
||||
/** The last cursor */
|
||||
private Cursor fLastCursor;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a vertical ruler with the given width.
|
||||
*
|
||||
* @param width the width of the vertical ruler
|
||||
*/
|
||||
public OverviewRuler(int width) {
|
||||
fWidth= width;
|
||||
}
|
||||
|
||||
public Control getControl() {
|
||||
return fCanvas;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return fWidth;
|
||||
}
|
||||
|
||||
private int getType(Annotation annotation) {
|
||||
if (annotation instanceof IProblemAnnotation) {
|
||||
IProblemAnnotation pa= (IProblemAnnotation) annotation;
|
||||
//if (!pa.isRelevant())
|
||||
// return UNKNOWN;
|
||||
if (pa.isTemporaryProblem())
|
||||
return TEMPORARY;
|
||||
if (pa.isError())
|
||||
return COMPILE_ERROR;
|
||||
if (pa.isWarning())
|
||||
return COMPILE_WARNING;
|
||||
}
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
public Control createControl(Composite parent, ITextViewer textViewer) {
|
||||
|
||||
fTextViewer= textViewer;
|
||||
|
||||
fHitDetectionCursor= new Cursor(parent.getDisplay(), SWT.CURSOR_HAND);
|
||||
fCanvas= new Canvas(parent, SWT.NO_BACKGROUND);
|
||||
|
||||
fCanvas.addPaintListener(new PaintListener() {
|
||||
public void paintControl(PaintEvent event) {
|
||||
if (fTextViewer != null)
|
||||
doubleBufferPaint(event.gc);
|
||||
}
|
||||
});
|
||||
|
||||
fCanvas.addDisposeListener(new DisposeListener() {
|
||||
public void widgetDisposed(DisposeEvent event) {
|
||||
handleDispose();
|
||||
fTextViewer= null;
|
||||
}
|
||||
});
|
||||
|
||||
fCanvas.addMouseListener(new MouseAdapter() {
|
||||
public void mouseDown(MouseEvent event) {
|
||||
handleMouseDown(event);
|
||||
}
|
||||
});
|
||||
|
||||
fCanvas.addMouseMoveListener(new MouseMoveListener() {
|
||||
public void mouseMove(MouseEvent event) {
|
||||
handleMouseMove(event);
|
||||
}
|
||||
});
|
||||
|
||||
if (fTextViewer != null)
|
||||
fTextViewer.addTextListener(fInternalListener);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (fHitDetectionCursor != null) {
|
||||
fHitDetectionCursor.dispose();
|
||||
fHitDetectionCursor= null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Double buffer drawing.
|
||||
*/
|
||||
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);
|
||||
doPaint(gc);
|
||||
} finally {
|
||||
gc.dispose();
|
||||
}
|
||||
|
||||
dest.drawImage(fBuffer, 0, 0);
|
||||
}
|
||||
|
||||
private Color getColor(RGB rgb) {
|
||||
CTextTools textTools= CPlugin.getDefault().getTextTools();
|
||||
return textTools.getColorManager().getColor(rgb);
|
||||
}
|
||||
|
||||
private void doPaint(GC gc) {
|
||||
|
||||
if (fTextViewer == null)
|
||||
return;
|
||||
|
||||
Rectangle r= new Rectangle(0, 0, 0, 0);
|
||||
int yy, hh= PROBLEM_HEIGHT_MIN;
|
||||
|
||||
|
||||
IDocument document= fTextViewer.getDocument();
|
||||
IRegion visible= fTextViewer.getVisibleRegion();
|
||||
|
||||
StyledText textWidget= fTextViewer.getTextWidget();
|
||||
int maxLines= textWidget.getLineCount();
|
||||
|
||||
Point size= fCanvas.getSize();
|
||||
int writable= maxLines * textWidget.getLineHeight();
|
||||
if (size.y > writable)
|
||||
size.y= writable;
|
||||
|
||||
for (int l= 0 ; l < LAYERS.length; l++) {
|
||||
|
||||
Iterator e= new FilterIterator(LAYERS[l]);
|
||||
Color fill= getColor(COLORS[LAYERS[l]][0]);
|
||||
Color stroke= getColor(COLORS[LAYERS[l]][1]);
|
||||
|
||||
for (int i= 0; e.hasNext(); i++) {
|
||||
|
||||
Annotation a= (Annotation) e.next();
|
||||
Position p= fModel.getPosition(a);
|
||||
|
||||
if (!p.overlapsWith(visible.getOffset(), visible.getLength()))
|
||||
continue;
|
||||
|
||||
int problemOffset= Math.max(p.getOffset(), visible.getOffset());
|
||||
int problemEnd= Math.min(p.getOffset() + p.getLength(), visible.getOffset() + visible.getLength());
|
||||
int problemLength= problemEnd - problemOffset;
|
||||
|
||||
try {
|
||||
|
||||
int startLine= textWidget.getLineAtOffset(problemOffset - visible.getOffset());
|
||||
yy= (startLine * size.y) / maxLines;
|
||||
|
||||
if (PROBLEM_HEIGHT_SCALABLE) {
|
||||
int numbersOfLines= document.getNumberOfLines(problemOffset, problemLength);
|
||||
hh= (numbersOfLines * size.y) / maxLines;
|
||||
if (hh < PROBLEM_HEIGHT_MIN)
|
||||
hh= PROBLEM_HEIGHT_MIN;
|
||||
}
|
||||
|
||||
if (fill != null) {
|
||||
gc.setBackground(fill);
|
||||
gc.fillRectangle(INSET, yy, size.x-(2*INSET), hh);
|
||||
}
|
||||
|
||||
if (stroke != null) {
|
||||
gc.setForeground(stroke);
|
||||
r.x= INSET;
|
||||
r.y= yy;
|
||||
r.width= size.x - (2 * INSET) - 1;
|
||||
r.height= hh;
|
||||
gc.setLineWidth(1);
|
||||
gc.drawRectangle(r);
|
||||
}
|
||||
} catch (BadLocationException x) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thread-safe implementation.
|
||||
* Can be called from any thread.
|
||||
*/
|
||||
public void update() {
|
||||
if (fCanvas != null && !fCanvas.isDisposed()) {
|
||||
Display d= fCanvas.getDisplay();
|
||||
if (d != null) {
|
||||
d.asyncExec(new Runnable() {
|
||||
public void run() {
|
||||
redraw();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redraws the overview ruler.
|
||||
*/
|
||||
private void redraw() {
|
||||
if (fCanvas != null && !fCanvas.isDisposed()) {
|
||||
GC gc= new GC(fCanvas);
|
||||
doubleBufferPaint(gc);
|
||||
gc.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private int[] toLineNumbers(int y_coordinate) {
|
||||
|
||||
IRegion visible= fTextViewer.getVisibleRegion();
|
||||
int lineNumber= 0;
|
||||
try {
|
||||
lineNumber= fTextViewer.getDocument().getLineOfOffset(visible.getOffset());
|
||||
} catch (BadLocationException x) {
|
||||
}
|
||||
|
||||
StyledText textWidget= fTextViewer.getTextWidget();
|
||||
int maxLines= textWidget.getContent().getLineCount();
|
||||
|
||||
Point size= fCanvas.getSize();
|
||||
int writable= maxLines * textWidget.getLineHeight();
|
||||
if (size.y > writable)
|
||||
size.y= writable;
|
||||
|
||||
int[] lines= new int[2];
|
||||
|
||||
int pixel= Math.max(y_coordinate - 1, 0);
|
||||
lines[0]= lineNumber + (pixel * maxLines) / size.y;
|
||||
|
||||
pixel= Math.min(size.y, y_coordinate + 1);
|
||||
lines[1]= lineNumber + (pixel * maxLines) / size.y;
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
private Position getProblemPositionAt(int[] lineNumbers) {
|
||||
|
||||
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();
|
||||
|
||||
Iterator e= new FilterIterator(ALL);
|
||||
while (e.hasNext()) {
|
||||
Annotation a= (Annotation) e.next();
|
||||
Position p= fModel.getPosition(a);
|
||||
if (start <= p.getOffset() && p.getOffset() < end) {
|
||||
if (found == null || p.getOffset() < found.getOffset())
|
||||
found= p;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (BadLocationException x) {
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private void handleMouseDown(MouseEvent event) {
|
||||
if (fTextViewer != null) {
|
||||
int[] lines= toLineNumbers(event.y);
|
||||
Position p= getProblemPositionAt(lines);
|
||||
if (p != null) {
|
||||
fTextViewer.revealRange(p.getOffset(), p.getLength());
|
||||
fTextViewer.setSelectedRange(p.getOffset(), p.getLength());
|
||||
}
|
||||
fTextViewer.getTextWidget().setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMouseMove(MouseEvent event) {
|
||||
if (fTextViewer != null) {
|
||||
int[] lines= toLineNumbers(event.y);
|
||||
Position p= getProblemPositionAt(lines);
|
||||
Cursor cursor= (p != null ? fHitDetectionCursor : null);
|
||||
if (cursor != fLastCursor) {
|
||||
fCanvas.setCursor(cursor);
|
||||
fLastCursor= cursor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue