rolled back

This commit is contained in:
Eugene Zhuravlev
2005-03-14 21:49:39 +03:00
parent 6b756f9a37
commit 997bf85062
@@ -26,6 +26,7 @@ import com.intellij.openapi.editor.markup.ErrorStripeRenderer;
import com.intellij.openapi.editor.markup.MarkupModel;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.util.SmartList;
import gnu.trove.TIntArrayList;
import javax.swing.*;
import java.awt.*;
@@ -48,221 +49,9 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
private List<ErrorStripeListener> myErrorMarkerListeners = new ArrayList<ErrorStripeListener>();
private ErrorStripeListener[] myCachedErrorMarkerListeners = null;
private List<RangeHighlighter> myCachedSortedHighlighters = null;
private MarkSpots myMarkSpots = new MarkSpots();
private ErrorMarkPileList myCachedErrorMarkPileList;
private int myScrollBarHeight;
private static class MarkSpot {
private int yStart;
private int yEnd;
private RangeHighlighter highlighter;
public boolean drawTopBorder;
public boolean drawBottomBorder;
public MarkSpot(final int yStart, final int yEnd, final RangeHighlighter highlighter) {
this.yStart = yStart;
this.yEnd = yEnd;
this.highlighter = highlighter;
}
private boolean near(MouseEvent e, double width) {
final int x = e.getX();
final int y = e.getY();
return 0 <= x && x < width && yStart - getMinHeight() <= y && y < yEnd + getMinHeight();
}
}
private class MarkSpots {
private List<MarkSpot> mySpots;
private List<MarkSpot> mySpotsSortedByLayer;
private void clear() {
mySpots = null;
mySpotsSortedByLayer = null;
}
public boolean showToolTipByMouseMove(final MouseEvent e, final double width) {
recalcMarkSpots();
LineTooltipRenderer bigRenderer = null;
List<RangeHighlighter> highlighters = new SmartList<RangeHighlighter>();
boolean wereInsideMarkSpot = false;
for (int i = 0; i < mySpots.size(); i++) {
MarkSpot markSpot = mySpots.get(i);
if (!markSpot.near(e, width)) {
if (wereInsideMarkSpot) break;
continue;
}
wereInsideMarkSpot = true;
RangeHighlighter marker = markSpot.highlighter;
highlighters.add(marker);
}
// move high priority tips up
Collections.sort(highlighters, new Comparator<RangeHighlighter>() {
public int compare(final RangeHighlighter o1, final RangeHighlighter o2) {
return o2.getLayer() - o1.getLayer();
}
});
List<HighlightInfo> infos = new SmartList<HighlightInfo>();
for (int i = 0; i < highlighters.size(); i++) {
RangeHighlighter marker = highlighters.get(i);
final Object tooltipObject = marker.getErrorStripeTooltip();
if (tooltipObject == null) continue;
if (tooltipObject instanceof HighlightInfo) {
infos.add((HighlightInfo)tooltipObject);
}
else {
final String text = tooltipObject.toString();
if (bigRenderer == null) {
bigRenderer = new LineTooltipRenderer(text);
}
else {
bigRenderer.addBelow(text);
}
}
}
if (infos.size() != 0) {
// show errors first
Collections.sort(infos, new Comparator<HighlightInfo>() {
public int compare(final HighlightInfo o1, final HighlightInfo o2) {
return o2.getSeverity().compareTo(o1.getSeverity());
}
});
final HighlightInfoComposite composite = new HighlightInfoComposite(infos);
if (bigRenderer == null) {
bigRenderer = new LineTooltipRenderer(composite.toolTip);
}
else {
final LineTooltipRenderer renderer = new LineTooltipRenderer(composite);
renderer.addBelow(bigRenderer.getText());
bigRenderer = renderer;
}
}
if (bigRenderer != null) {
showTooltip(e, bigRenderer);
return true;
}
return false;
}
private void recalcMarkSpots() {
if (mySpots != null) return;
final List<RangeHighlighter> sortedHighlighters = getSortedHighlighters();
mySpots = new ArrayList<MarkSpot>();
int prevEndPosition = 0;
boolean prevIsThin = false;
for (int i = 0; i < sortedHighlighters.size(); i++) {
RangeHighlighter mark = sortedHighlighters.get(i);
if (!mark.isValid() || mark.getErrorStripeMarkColor() == null) return;
int visStartLine = myEditor.logicalToVisualPosition(
new LogicalPosition(mark.getDocument().getLineNumber(mark.getStartOffset()), 0)
).line;
int visEndLine = myEditor.logicalToVisualPosition(
new LogicalPosition(mark.getDocument().getLineNumber(mark.getEndOffset()), 0)
).line;
int yStartPosition = visibleLineToYPosition(visStartLine, myScrollBarHeight);
int yEndPosition = visibleLineToYPosition(visEndLine, myScrollBarHeight);
if (yEndPosition - yStartPosition < getMinHeight()) {
yEndPosition = yStartPosition + getMinHeight();
}
final MarkSpot markSpot = new MarkSpot(yStartPosition, yEndPosition, mark);
markSpot.drawTopBorder = mark.isThinErrorStripeMark() != prevIsThin || prevEndPosition < yStartPosition;
mySpots.add(markSpot);
if (i != 0 && mySpots.get(i-1).yEnd < yStartPosition) {
mySpots.get(i-1).drawBottomBorder = true;
}
if (i == mySpots.size()-1) {
markSpot.drawBottomBorder = true;
}
prevEndPosition = yEndPosition;
prevIsThin = mark.isThinErrorStripeMark();
}
mySpotsSortedByLayer = new ArrayList<MarkSpot>(mySpots);
Collections.sort(mySpotsSortedByLayer, new Comparator<MarkSpot>() {
public int compare(final MarkSpot o1, final MarkSpot o2) {
return o1.highlighter.getLayer() - o2.highlighter.getLayer();
}
});
}
private void repaint(Graphics g, final int width) {
recalcMarkSpots();
for (int i = 0; i < mySpotsSortedByLayer.size(); i++) {
MarkSpot markSpot = mySpotsSortedByLayer.get(i);
int y = markSpot.yStart;
RangeHighlighter mark = markSpot.highlighter;
int yEndPosition = markSpot.yEnd;
final int height = yEndPosition - y;
final Color color = mark.getErrorStripeMarkColor();
g.setColor(color);
int x = 1;
int paintWidth = width;
if (mark.isThinErrorStripeMark()) {
paintWidth /= 2;
x += paintWidth / 2;
}
g.fillRect(x, y, paintWidth - 1, height);
Color brighter = color.brighter();
Color darker = color.darker();
g.setColor(brighter);
g.drawLine(x, y, x, y + height);
if (markSpot.drawTopBorder) {
g.drawLine(x + 1, y, x + paintWidth - 1, y);
}
g.setColor(darker);
if (markSpot.drawBottomBorder) {
g.drawLine(x + 1, y + height, x + paintWidth, y + height);
}
g.drawLine(x + paintWidth, y, x + paintWidth, y + height - 1);
}
}
public void doClick(final MouseEvent e, final int width) {
recalcMarkSpots();
MarkSpot nearestSpot = null;
for (int i = 0; i < mySpots.size(); i++) {
MarkSpot markSpot = mySpots.get(i);
if (markSpot.near(e, width)) {
if (nearestSpot == null || Math.abs(nearestSpot.yStart - e.getY()) > Math.abs(markSpot.yStart - e.getY())) {
nearestSpot = markSpot;
}
}
else {
if (nearestSpot != null) break;
}
}
if (nearestSpot == null) return;
RangeHighlighter marker = nearestSpot.highlighter;
int offset = marker.getStartOffset();
final Document doc = myEditor.getDocument();
if (doc.getLineCount() > 0) {
// Necessary to expand folded block even if navigating just before one
// Very useful when navigating to first unused import statement.
int lineEnd = doc.getLineEndOffset(doc.getLineNumber(offset));
myEditor.getCaretModel().moveToOffset(lineEnd);
}
myEditor.getCaretModel().moveToOffset(offset);
myEditor.getSelectionModel().removeSelection();
ScrollingModel scrollingModel = myEditor.getScrollingModel();
scrollingModel.disableAnimation();
scrollingModel.scrollToCaret(ScrollType.CENTER);
scrollingModel.enableAnimation();
fireErrorMarkerClicked(marker, e);
}
}
EditorMarkupModelImpl(EditorImpl editor) {
super((DocumentImpl)editor.getDocument());
myEditor = editor;
@@ -328,13 +117,18 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
if (myCachedSortedHighlighters.size() != 0) {
Collections.sort(myCachedSortedHighlighters, new Comparator<RangeHighlighter>() {
public int compare(final RangeHighlighter h1, final RangeHighlighter h2) {
return h1.getStartOffset() - h2.getStartOffset();
Collections.sort(
myCachedSortedHighlighters, new Comparator() {
public int compare(Object o1, Object o2) {
RangeHighlighter h1 = (RangeHighlighter)o1;
RangeHighlighter h2 = (RangeHighlighter)o2;
return h1.getStartOffset() - h2.getEndOffset();
}
}
});
);
}
}
return myCachedSortedHighlighters;
}
@@ -367,7 +161,8 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
myErrorStripeRenderer.paint(this, g, new Rectangle(0, 0, top, getWidth()));
}
myMarkSpots.repaint(g,getWidth());
final ErrorMarkPileList markPileList = getErrorMarkPileList();
markPileList.paint(g, getWidth());
}
finally {
((ApplicationImpl)ApplicationManager.getApplication()).editorPaintFinish();
@@ -392,7 +187,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
if (lineCount == 0) {
return;
}
myMarkSpots.doClick(e, getWidth());
getErrorMarkPileList().doClick(e, getWidth());
}
public void mouseMoved(MouseEvent e) {
@@ -409,7 +204,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
return;
}
if (myMarkSpots.showToolTipByMouseMove(e,getWidth())) {
if (getErrorMarkPileList().showToolTipByMouseMove(e,getWidth())) {
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
return;
}
@@ -498,10 +293,230 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
public void markDirtied() {
myCachedSortedHighlighters = null;
myMarkSpots.clear();
myCachedErrorMarkPileList = null;
}
private ErrorMarkPileList getErrorMarkPileList() {
if (myCachedErrorMarkPileList == null) {
myCachedErrorMarkPileList = new ErrorMarkPileList();
List<RangeHighlighter> sortedHighlighters = getSortedHighlighters();
for (int i = 0; i < sortedHighlighters.size(); i++) {
RangeHighlighter highlighter = sortedHighlighters.get(i);
myCachedErrorMarkPileList.addNextMark(highlighter);
}
}
return myCachedErrorMarkPileList;
}
private class ErrorMarkPileList {
private List<ErrorMarkPile> list = new ArrayList<ErrorMarkPile>();
private void addNextMark(RangeHighlighter mark) {
if (!mark.isValid() || mark.getErrorStripeMarkColor() == null) return;
int visStartLine = myEditor.logicalToVisualPosition(
new LogicalPosition(mark.getDocument().getLineNumber(mark.getStartOffset()), 0)
).line;
int visEndLine = myEditor.logicalToVisualPosition(
new LogicalPosition(mark.getDocument().getLineNumber(mark.getEndOffset()), 0)
).line;
int yStartPosition = visibleLineToYPosition(visStartLine, myScrollBarHeight);
int yEndPosition = visibleLineToYPosition(visEndLine, myScrollBarHeight);
final ErrorMarkPile prevPile = list.size() == 0 ? null : list.get(list.size() - 1);
int prevPileStart = prevPile == null ? 0 : prevPile.yStart;
if (prevPile != null && yStartPosition - prevPileStart < getMinHeight()) {
prevPile.addMark(mark, yStartPosition, yEndPosition);
}
else {
final ErrorMarkPile pile = new ErrorMarkPile(yStartPosition);
pile.addMark(mark, yStartPosition, yEndPosition);
list.add(pile);
}
}
public void paint(final Graphics g, final int width) {
for (int i = 0; i < list.size(); i++) {
ErrorMarkPile pile = list.get(i);
pile.paint(g, width);
}
}
public void doClick(final MouseEvent e, final double width) {
for (int i = 0; i < list.size(); i++) {
ErrorMarkPile pile = list.get(i);
if (pile.doClick(e, width)) return;
}
}
public boolean showToolTipByMouseMove(final MouseEvent e, double width) {
for (int i = 0; i < list.size(); i++) {
ErrorMarkPile pile = list.get(i);
if (pile.showToolTipByMouseMove(e, width)) return true;
}
return false;
}
}
private static int getMinHeight() {
return DaemonCodeAnalyzerSettings.getInstance().getErrorStripeMarkMinHeight();
}
// number of error marks glued together
private class ErrorMarkPile {
private int yStart;
private int yEnd;
private List<RangeHighlighter> markers = new ArrayList<RangeHighlighter>();
private TIntArrayList paintingEndOffsets = new TIntArrayList();
public ErrorMarkPile(final int yStart) {
this.yStart = yStart;
}
public void addMark(final RangeHighlighter mark, int newYStart, int newYEnd) {
if (newYEnd - newYStart < getMinHeight()) {
newYEnd = newYStart + getMinHeight();
}
yEnd = Math.max(yEnd, newYEnd - yStart < getMinHeight() ? yStart + getMinHeight() : newYEnd);
if (markers.size() != 0) {
final int prevMarkIndex = markers.size() - 1;
final RangeHighlighter prevMark = markers.get(prevMarkIndex);
final int prevMarkEnd = paintingEndOffsets.get(prevMarkIndex);
if (prevMark.getLayer() < mark.getLayer()) {
// prev mark prio is lower, shorten prev mark
paintingEndOffsets.set(prevMarkIndex, Math.min(prevMarkEnd, newYStart));
}
else if (prevMarkEnd > newYEnd) {
// just drop new mark as it falls in the middle of higher priority other mark
return;
}
}
markers.add(mark);
paintingEndOffsets.add(newYEnd);
}
public void paint(final Graphics g, final int width) {
int y = yStart;
for (int i = 0; i < markers.size(); i++) {
RangeHighlighter mark = markers.get(i);
int yEndPosition = i == markers.size() - 1 ? yEnd : paintingEndOffsets.get(i);
final int height = yEndPosition - y;
final Color color = mark.getErrorStripeMarkColor();
g.setColor(color);
int x = 1;
int paintWidth = width;
if (mark.isThinErrorStripeMark()) {
paintWidth /= 2;
x += paintWidth / 2;
}
g.fillRect(x, y, paintWidth - 1, height);
Color brighter = color.brighter();
Color darker = color.darker();
g.setColor(brighter);
g.drawLine(x, y, x, y + height);
if (i == 0 || markers.get(i-1).isThinErrorStripeMark() != mark.isThinErrorStripeMark()) {
g.drawLine(x + 1, y, x + paintWidth - 1, y);
}
g.setColor(darker);
if (i == markers.size()-1 || markers.get(i + 1).isThinErrorStripeMark() != mark.isThinErrorStripeMark()) {
g.drawLine(x + 1, y + height, x + paintWidth, y + height);
}
g.drawLine(x + paintWidth, y, x + paintWidth, y + height - 1);
y = yEndPosition;
}
}
public boolean doClick(final MouseEvent e, final double width) {
if (!inside(e, width)) {
return false;
}
final int y = e.getY();
RangeHighlighter marker = markers.get(0);
int offset = marker.getStartOffset();
for (int i = 0; i< paintingEndOffsets.size(); i++) {
final int endY = paintingEndOffsets.get(i);
if (y < endY) {
marker = markers.get(i);
offset = marker.getStartOffset();
break;
}
}
final Document doc = myEditor.getDocument();
if (doc.getLineCount() > 0) {
// Necessary to expand folded block even if naviagting just before one
// Very useful when navigating to first unused import statement.
int lineEnd = doc.getLineEndOffset(doc.getLineNumber(offset));
myEditor.getCaretModel().moveToOffset(lineEnd);
}
myEditor.getCaretModel().moveToOffset(offset);
myEditor.getSelectionModel().removeSelection();
ScrollingModel scrollingModel = myEditor.getScrollingModel();
scrollingModel.disableAnimation();
scrollingModel.scrollToCaret(ScrollType.CENTER);
scrollingModel.enableAnimation();
fireErrorMarkerClicked(marker, e);
return true;
}
private boolean inside(MouseEvent e, double width) {
final int x = e.getX();
final int y = e.getY();
return 0 <= x && x < width && yStart <= y && y < yEnd;
}
public boolean showToolTipByMouseMove(final MouseEvent e, final double width) {
if (!inside(e, width)) {
return false;
}
LineTooltipRenderer bigRenderer = null;
List<HighlightInfo> infos = new SmartList<HighlightInfo>();
for (int i = 0; i < markers.size(); i++) {
RangeHighlighter marker = markers.get(i);
final Object tooltipObject = marker.getErrorStripeTooltip();
if (tooltipObject == null) continue;
if (tooltipObject instanceof HighlightInfo) {
infos.add((HighlightInfo)tooltipObject);
}
else {
final String text = tooltipObject.toString();
if (bigRenderer == null) {
bigRenderer = new LineTooltipRenderer(text);
}
else {
bigRenderer.addBelow(text);
}
}
}
if (infos.size() != 0) {
// show errors first
Collections.sort(infos, new Comparator<HighlightInfo>() {
public int compare(final HighlightInfo o1, final HighlightInfo o2) {
return o2.getSeverity().compareTo(o1.getSeverity());
}
});
final HighlightInfoComposite composite = new HighlightInfoComposite(infos);
if (bigRenderer == null) {
bigRenderer = new LineTooltipRenderer(composite.toolTip);
}
else {
bigRenderer.addBelow(composite.toolTip);
}
}
if (bigRenderer != null) {
showTooltip(e, bigRenderer);
}
return true;
}
}
}