From 15b40716ca7a792e80bc38cd81a3b4e9e018d508 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 21 Feb 2005 21:15:36 +0300 Subject: [PATCH] (no message) --- .../lang/annotation/HighlightSeverity.java | 10 +- .../daemon/impl/DaemonCodeAnalyzerImpl.java | 6 +- .../daemon/impl/HighlightInfo.java | 2 +- .../daemon/impl/LocalInspectionsPass.java | 23 ++- .../hint/DocumentFragmentTooltipRenderer.java | 68 ++++++++ .../codeInsight/hint/LineTooltipRenderer.java | 155 +++++++++++++++++ .../codeInsight/hint/TooltipController.java | 164 ++---------------- .../codeInsight/hint/TooltipRenderer.java | 17 ++ .../impl/EditorGutterComponentImpl.java | 3 +- .../openapi/editor/impl/EditorImpl.java | 3 +- .../editor/impl/EditorMarkupModelImpl.java | 89 +++++----- .../openapi/vcs/ex/LineStatusTracker.java | 5 +- util/src/com/intellij/util/SmartList.java | 7 + 13 files changed, 329 insertions(+), 223 deletions(-) create mode 100644 source/com/intellij/codeInsight/hint/DocumentFragmentTooltipRenderer.java create mode 100644 source/com/intellij/codeInsight/hint/LineTooltipRenderer.java create mode 100644 source/com/intellij/codeInsight/hint/TooltipRenderer.java diff --git a/openapi/src/com/intellij/lang/annotation/HighlightSeverity.java b/openapi/src/com/intellij/lang/annotation/HighlightSeverity.java index 06322050d255..c46c49c7d52d 100644 --- a/openapi/src/com/intellij/lang/annotation/HighlightSeverity.java +++ b/openapi/src/com/intellij/lang/annotation/HighlightSeverity.java @@ -7,7 +7,7 @@ package com.intellij.lang.annotation; * Time: 4:23:09 PM * To change this template use File | Settings | File Templates. */ -public class HighlightSeverity { +public class HighlightSeverity implements Comparable { private final String myName; // for debug only private final int myVal; public static final HighlightSeverity INFORMATION = new HighlightSeverity("INFORMATION", 0); @@ -23,11 +23,7 @@ public class HighlightSeverity { return myName; } - public boolean isGreaterOrEqual(HighlightSeverity severity) { - return myVal >= severity.myVal; - } - - public boolean isLess(HighlightSeverity severity) { - return myVal < severity.myVal; + public int compareTo(final HighlightSeverity highlightSeverity) { + return myVal - highlightSeverity.myVal; } } diff --git a/source/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java b/source/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java index 39839df8d792..5a678270a0bc 100644 --- a/source/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java +++ b/source/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java @@ -391,7 +391,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx ArrayList array = new ArrayList(); for (int i = 0; i < highlights.length; i++) { HighlightInfo info = highlights[i]; - if (info.getSeverity().isGreaterOrEqual(minSeverity)) { + if (info.getSeverity().compareTo(minSeverity) >=0) { array.add(info); } } @@ -426,10 +426,10 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx if (foundInfoList.size() != 0) { final HighlightInfo foundInfo = foundInfoList.get(0); - if (foundInfo.getSeverity().isLess(info.getSeverity())) { + if (foundInfo.getSeverity().compareTo(info.getSeverity()) < 0) { foundInfoList.clear(); } - else if (info.getSeverity().isLess(foundInfo.getSeverity())) { + else if (info.getSeverity().compareTo(foundInfo.getSeverity()) < 0) { continue; } } diff --git a/source/com/intellij/codeInsight/daemon/impl/HighlightInfo.java b/source/com/intellij/codeInsight/daemon/impl/HighlightInfo.java index bbd450b660bd..e5f779125c62 100644 --- a/source/com/intellij/codeInsight/daemon/impl/HighlightInfo.java +++ b/source/com/intellij/codeInsight/daemon/impl/HighlightInfo.java @@ -129,7 +129,7 @@ public class HighlightInfo { public String description; public String toolTip; - public HighlightSeverity severity; + public final HighlightSeverity severity; public boolean isAfterEndOfLine = false; public int navigationShift = 0; diff --git a/source/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java b/source/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java index 4ee1d72b2cfb..a3cdeca79a3d 100644 --- a/source/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java +++ b/source/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java @@ -1,14 +1,11 @@ package com.intellij.codeInsight.daemon.impl; -import com.intellij.application.options.ErrorHighlightingOptions; -import com.intellij.application.options.ErrorHighlightingPanel; import com.intellij.codeHighlighting.HighlightDisplayLevel; import com.intellij.codeInsight.CodeInsightUtil; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings; import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction; -import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.InspectionManager; import com.intellij.codeInspection.LocalInspectionTool; import com.intellij.codeInspection.ProblemDescriptor; @@ -21,9 +18,9 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.ex.EditorMarkupModel; import com.intellij.openapi.editor.markup.ErrorStripeRenderer; -import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; @@ -31,7 +28,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.IncorrectOperationException; import gnu.trove.THashSet; import java.util.*; @@ -181,16 +177,25 @@ public class LocalInspectionsPass extends TextEditorHighlightingPass { //TODO PsiElement psiElement = descriptor.getPsiElement(); String message = renderDescriptionMessage(descriptor); - HighlightInfoType level = myLevels.get(i); + final HighlightInfoType level = myLevels.get(i); final HighlightDisplayKey key = HighlightDisplayKey.find(tool.getShortName()); final InspectionProfileImpl inspectionProfile = DaemonCodeAnalyzerSettings.getInstance().getInspectionProfile(); if (!inspectionProfile.isToolEnabled(key)) continue; - boolean isError = inspectionProfile.getErrorLevel(key) == HighlightDisplayLevel.ERROR; + final boolean isError = inspectionProfile.getErrorLevel(key) == HighlightDisplayLevel.ERROR; - final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(level, psiElement, message, message); + + final HighlightInfoType type = new HighlightInfoType() { + public HighlightSeverity getSeverity() { + return isError ? HighlightSeverity.ERROR : HighlightSeverity.WARNING; + } + + public TextAttributesKey getAttributesKey() { + return level.getAttributesKey(); + } + }; + final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(type, psiElement, message, message); infos.add(highlightInfo); - highlightInfo.severity = isError ? HighlightSeverity.ERROR : HighlightSeverity.WARNING; if (descriptor.getFix() != null) { QuickFixAction.registerQuickFixAction(highlightInfo, new QuickFixWrapper(descriptor)); } diff --git a/source/com/intellij/codeInsight/hint/DocumentFragmentTooltipRenderer.java b/source/com/intellij/codeInsight/hint/DocumentFragmentTooltipRenderer.java new file mode 100644 index 000000000000..00b773ff6464 --- /dev/null +++ b/source/com/intellij/codeInsight/hint/DocumentFragmentTooltipRenderer.java @@ -0,0 +1,68 @@ +package com.intellij.codeInsight.hint; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.DocumentFragment; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.editor.ex.FoldingModelEx; +import com.intellij.openapi.util.TextRange; +import com.intellij.ui.LightweightHint; + +import javax.swing.*; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * User: cdr + * Date: Feb 21, 2005 + * Time: 7:14:29 PM + * To change this template use File | Settings | File Templates. + */ +public class DocumentFragmentTooltipRenderer implements TooltipRenderer { + private final DocumentFragment myDocumentFragment; + + public DocumentFragmentTooltipRenderer(DocumentFragment documentFragment) { + myDocumentFragment = documentFragment; + } + + public LightweightHint show(final Editor editor, Point p, boolean alignToRight, TooltipGroup group) { + LightweightHint hint; + + final JComponent editorComponent = editor.getComponent(); + + TextRange range = myDocumentFragment.getTextRange(); + int startOffset = range.getStartOffset(); + int endOffset = range.getEndOffset(); + Document doc = myDocumentFragment.getDocument(); + int endLine = doc.getLineNumber(endOffset); + int startLine = doc.getLineNumber(startOffset); + + JLayeredPane layeredPane = editorComponent.getRootPane().getLayeredPane(); + + p = editor.logicalPositionToXY(new LogicalPosition(startLine, 0)); + p = SwingUtilities.convertPoint( + ((EditorEx)editor).getGutterComponentEx(), + p, + layeredPane + ); + + p.x -= 3; + p.y += editor.getLineHeight(); + + Point screen = new Point(p); + SwingUtilities.convertPointToScreen(screen, layeredPane); + int maxLineCount = (Toolkit.getDefaultToolkit().getScreenSize().height - screen.y) / editor.getLineHeight(); + + if (endLine - startLine > maxLineCount) { + endOffset = doc.getLineEndOffset(Math.min(startLine + maxLineCount, doc.getLineCount() - 1)); + } + + FoldingModelEx foldingModel = (FoldingModelEx)editor.getFoldingModel(); + foldingModel.setFoldingEnabled(false); + TextRange textRange = new TextRange(startOffset, endOffset); + hint = EditorFragmentComponent.showEditorFragmentHintAt(editor, textRange, p.x, p.y, false, false); + foldingModel.setFoldingEnabled(true); + return hint; + } +} diff --git a/source/com/intellij/codeInsight/hint/LineTooltipRenderer.java b/source/com/intellij/codeInsight/hint/LineTooltipRenderer.java new file mode 100644 index 000000000000..1d762296d43c --- /dev/null +++ b/source/com/intellij/codeInsight/hint/LineTooltipRenderer.java @@ -0,0 +1,155 @@ +package com.intellij.codeInsight.hint; + +import com.intellij.codeInsight.daemon.impl.HighlightInfo; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.ui.MultiLineLabelUI; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.LightweightHint; +import com.intellij.ui.SplittingUtil; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * Created by IntelliJ IDEA. + * User: cdr + * Date: Feb 21, 2005 + * Time: 7:17:54 PM + * To change this template use File | Settings | File Templates. + */ +public class LineTooltipRenderer implements TooltipRenderer { + private String myText; + + public LineTooltipRenderer(String text) { + myText = text; + } + + public LineTooltipRenderer(HighlightInfo highlightInfo) { + this(highlightInfo.toolTip); + } + + public LightweightHint show(final Editor editor, Point p, boolean alignToRight, TooltipGroup group) { + + final HintManager hintManager = HintManager.getInstance(); + LightweightHint hint; + + final JComponent editorComponent = editor.getComponent(); + JLabel label = new JLabel(); + final JComponent contentComponent = editor.getContentComponent(); + // This listeners makes hint transparent for mouse events. It means that hint is closed + // by MousePressed and this MousePressed goes into the underlying editor component. + label.addMouseListener( + new MouseAdapter() { + public void mousePressed(MouseEvent e) { + MouseEvent newMouseEvent = SwingUtilities.convertMouseEvent(e.getComponent(), e, contentComponent); + hintManager.hideAllHints(); + contentComponent.dispatchEvent(newMouseEvent); + } + } + ); + + label.setBorder( + BorderFactory.createCompoundBorder( + BorderFactory.createLineBorder(Color.black), + BorderFactory.createEmptyBorder(0, 5, 0, 5) + ) + ); + label.setForeground(Color.black); + label.setBackground(HintUtil.INFORMATION_COLOR); + label.setOpaque(true); + + String text = myText; + + if (text == null) return null; + label.setText(text); + int width = label.getPreferredSize().width; + + JLayeredPane layeredPane = editorComponent.getRootPane().getLayeredPane(); + + int widthLimit = layeredPane.getWidth() - 10; + int heightLimit = layeredPane.getHeight() - 5; + if (text.indexOf("") < 0 && width > widthLimit / 3) { + label.setUI(new MultiLineLabelUI()); + text = splitText(label, text, widthLimit); + label.setText(text); + } + + if (alignToRight) { + p.x -= label.getPreferredSize().width; + } + + // try to make cursor outside tooltip. SCR 15038 + p.x += 3; + p.y += 3; + width = label.getPreferredSize().width; + if (p.x + width >= widthLimit) { + p.x = widthLimit - width; + } + if (p.x < 3) { + p.x = 3; + } + + int height = label.getPreferredSize().height; + if (p.y + height > heightLimit) { + p.y = heightLimit - height; + } + hint = new LightweightHint(label); + hintManager.showEditorHint(hint, editor, p, + HintManager.HIDE_BY_ANY_KEY | HintManager.HIDE_BY_TEXT_CHANGE | HintManager.HIDE_BY_OTHER_HINT | + HintManager.HIDE_BY_SCROLLING, 0, false); + return hint; + } + + /** + * @return text splitted with '\n' + */ + private static String splitText(JLabel label, String text, int widthLimit) { + FontMetrics fontMetrics = label.getFontMetrics(label.getFont()); + + String[] lines = SplittingUtil.splitText(text, fontMetrics, widthLimit, ' '); + + StringBuffer result = new StringBuffer(); + for (int i = 0; i < lines.length; i++) { + String line = lines[i]; + if (i > 0) { + result.append('\n'); + } + result.append(line); + } + return result.toString(); + } + + public void addBelow(String text) { + String html1 = getHtmlBody(myText); + String html2 = getHtmlBody(text); + myText = "" + html1 + "
" + html2 + ""; + } + + private String getHtmlBody(String text) { + if (!text.startsWith("")) { + return text.replaceAll("\n","
"); + } + text = StringUtil.trimStart(text, "").trim(); + text = StringUtil.trimEnd(text, "").trim(); + text = StringUtil.trimStart(text, "").trim(); + text = StringUtil.trimEnd(text, "").trim(); + return text; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof LineTooltipRenderer)) return false; + + final LineTooltipRenderer lineTooltipRenderer = (LineTooltipRenderer)o; + + if (myText != null ? !myText.equals(lineTooltipRenderer.myText) : lineTooltipRenderer.myText != null) return false; + + return true; + } + + public int hashCode() { + return (myText != null ? myText.hashCode() : 0); + } +} diff --git a/source/com/intellij/codeInsight/hint/TooltipController.java b/source/com/intellij/codeInsight/hint/TooltipController.java index 4482e811c931..2a7b22d17520 100644 --- a/source/com/intellij/codeInsight/hint/TooltipController.java +++ b/source/com/intellij/codeInsight/hint/TooltipController.java @@ -1,27 +1,18 @@ package com.intellij.codeInsight.hint; import com.intellij.codeInsight.daemon.impl.HighlightInfo; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.DocumentFragment; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.LogicalPosition; -import com.intellij.openapi.editor.ex.EditorEx; -import com.intellij.openapi.editor.ex.FoldingModelEx; -import com.intellij.openapi.ui.MultiLineLabelUI; import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.TextRange; import com.intellij.ui.LightweightHint; -import com.intellij.ui.SplittingUtil; import com.intellij.util.Alarm; import javax.swing.*; import java.awt.*; -import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class TooltipController { private LightweightHint myCurrentTooltip; - private Object myCurrentTooltipObject; + private TooltipRenderer myCurrentTooltipObject; private TooltipGroup myCurrentTooltipGroup; private Alarm myTooltipAlarm = new Alarm(); @@ -38,7 +29,7 @@ public class TooltipController { public void showTooltipByMouseMove(final Editor editor, MouseEvent e, - final Object tooltipObject, + final TooltipRenderer tooltipObject, final boolean alignToRight, final TooltipGroup group) { myTooltipAlarm.cancelAllRequests(); if (myCurrentTooltip == null || !myCurrentTooltip.isVisible()) { @@ -79,157 +70,28 @@ public class TooltipController { } } - /** - * @param p point in layered pane coordinate system - * @param group - */ - public void showTooltip(final Editor editor, Point p, Object tooltipObject, boolean alignToRight, TooltipGroup group) { + public void showTooltip(final Editor editor, Point p, String text, boolean alignToRight, TooltipGroup group) { + showTooltip(editor, p, new LineTooltipRenderer(text), alignToRight, group); + } + public void showTooltip(final Editor editor, Point p, HighlightInfo info, boolean alignToRight, TooltipGroup group) { + showTooltip(editor, p, new LineTooltipRenderer(info), alignToRight, group); + } + public void showTooltip(final Editor editor, Point p, TooltipRenderer tooltipRenderer, boolean alignToRight, TooltipGroup group) { myTooltipAlarm.cancelAllRequests(); if (myCurrentTooltip == null || !myCurrentTooltip.isVisible()) { myCurrentTooltipObject = null; } - if (Comparing.equal(tooltipObject, myCurrentTooltipObject)) return; + if (Comparing.equal(tooltipRenderer, myCurrentTooltipObject)) return; if (myCurrentTooltipGroup != null && group.compareTo(myCurrentTooltipGroup) < 0) return; p = new Point(p); hideCurrentTooltip(); + LightweightHint hint = tooltipRenderer.show(editor, p, alignToRight, group); + myCurrentTooltipGroup = group; - - final HintManager hintManager = HintManager.getInstance(); - LightweightHint hint; - - final JComponent editorComponent = editor.getComponent(); - if (tooltipObject instanceof DocumentFragment) { - DocumentFragment fragment = (DocumentFragment)tooltipObject; - - TextRange range = fragment.getTextRange(); - int startOffset = range.getStartOffset(); - int endOffset = range.getEndOffset(); - Document doc = fragment.getDocument(); - int endLine = doc.getLineNumber(endOffset); - int startLine = doc.getLineNumber(startOffset); - - JLayeredPane layeredPane = editorComponent.getRootPane().getLayeredPane(); - - p = editor.logicalPositionToXY(new LogicalPosition(startLine, 0)); - p = SwingUtilities.convertPoint( - ((EditorEx)editor).getGutterComponentEx(), - p, - layeredPane - ); - - p.x -= 3; - p.y += editor.getLineHeight(); - - Point screen = new Point(p); - SwingUtilities.convertPointToScreen(screen, layeredPane); - int maxLineCount = (Toolkit.getDefaultToolkit().getScreenSize().height - screen.y) / editor.getLineHeight(); - - if (endLine - startLine > maxLineCount) { - endOffset = doc.getLineEndOffset(Math.min(startLine + maxLineCount, doc.getLineCount() - 1)); - } - - FoldingModelEx foldingModel = (FoldingModelEx)editor.getFoldingModel(); - foldingModel.setFoldingEnabled(false); - TextRange textRange = new TextRange(startOffset, endOffset); - hint = EditorFragmentComponent.showEditorFragmentHintAt(editor, textRange, p.x, p.y, false, false); - foldingModel.setFoldingEnabled(true); - } - else { - JLabel label = new JLabel(); - final JComponent contentComponent = editor.getContentComponent(); - // This listeners makes hint transparent for mouse events. It means that hint is closed - // by MousePressed and this MousePressed goes into the underlying editor component. - label.addMouseListener( - new MouseAdapter() { - public void mousePressed(MouseEvent e) { - MouseEvent newMouseEvent = SwingUtilities.convertMouseEvent(e.getComponent(), e, contentComponent); - hintManager.hideAllHints(); - contentComponent.dispatchEvent(newMouseEvent); - } - } - ); - - label.setBorder( - BorderFactory.createCompoundBorder( - BorderFactory.createLineBorder(Color.black), - BorderFactory.createEmptyBorder(0, 5, 0, 5) - ) - ); - label.setForeground(Color.black); - label.setBackground(HintUtil.INFORMATION_COLOR); - label.setOpaque(true); - - String text; - if (tooltipObject instanceof HighlightInfo) { - HighlightInfo info = (HighlightInfo)tooltipObject; - text = info.toolTip; - } - else { - text = tooltipObject.toString(); - } - - if (text == null) return; - label.setText(text); - int width = label.getPreferredSize().width; - - JLayeredPane layeredPane = editorComponent.getRootPane().getLayeredPane(); - - int widthLimit = layeredPane.getWidth() - 10; - int heightLimit = layeredPane.getHeight() - 5; - if (text.indexOf("") < 0 && width > widthLimit / 3) { - label.setUI(new MultiLineLabelUI()); - text = splitText(label, text, widthLimit); - label.setText(text); - } - - if (alignToRight) { - p.x -= label.getPreferredSize().width; - } - - // try to make cursor outside tooltip. SCR 15038 - p.x += 3; - p.y += 3; - width = label.getPreferredSize().width; - if (p.x + width >= widthLimit) { - p.x = widthLimit - width; - } - if (p.x < 3) { - p.x = 3; - } - - int height = label.getPreferredSize().height; - if (p.y + height > heightLimit) { - p.y = heightLimit - height; - } - hint = new LightweightHint(label); - hintManager.showEditorHint(hint, editor, p, - HintManager.HIDE_BY_ANY_KEY | HintManager.HIDE_BY_TEXT_CHANGE | HintManager.HIDE_BY_OTHER_HINT | - HintManager.HIDE_BY_SCROLLING, 0, false); - } - myCurrentTooltip = hint; - myCurrentTooltipObject = tooltipObject; - } - - /** - * @return text splitted with '\n' - */ - private static String splitText(JLabel label, String text, int widthLimit) { - FontMetrics fontMetrics = label.getFontMetrics(label.getFont()); - - String[] lines = SplittingUtil.splitText(text, fontMetrics, widthLimit, ' '); - - StringBuffer result = new StringBuffer(); - for (int i = 0; i < lines.length; i++) { - String line = lines[i]; - if (i > 0) { - result.append('\n'); - } - result.append(line); - } - return result.toString(); + myCurrentTooltipObject = tooltipRenderer; } } \ No newline at end of file diff --git a/source/com/intellij/codeInsight/hint/TooltipRenderer.java b/source/com/intellij/codeInsight/hint/TooltipRenderer.java new file mode 100644 index 000000000000..0d9428743021 --- /dev/null +++ b/source/com/intellij/codeInsight/hint/TooltipRenderer.java @@ -0,0 +1,17 @@ +package com.intellij.codeInsight.hint; + +import com.intellij.openapi.editor.Editor; +import com.intellij.ui.LightweightHint; + +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * User: cdr + * Date: Feb 21, 2005 + * Time: 7:11:53 PM + * To change this template use File | Settings | File Templates. + */ +public interface TooltipRenderer { + LightweightHint show(final Editor editor, Point p, boolean alignToRight, TooltipGroup group); +} diff --git a/source/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/source/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index ea27acdbeb6b..4425c2ba74ce 100644 --- a/source/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/source/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -11,6 +11,7 @@ package com.intellij.openapi.editor.impl; import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.hint.TooltipController; import com.intellij.codeInsight.hint.TooltipGroup; +import com.intellij.codeInsight.hint.LineTooltipRenderer; import com.intellij.ide.ui.LafManager; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; @@ -894,7 +895,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse TooltipController controller = HintManager.getInstance().getTooltipController(); if (tooltip != null && tooltip.length() != 0) { - controller.showTooltipByMouseMove(myEditor, e, tooltip, false, GUTTER_TOOLTIP_GROUP); + controller.showTooltipByMouseMove(myEditor, e, new LineTooltipRenderer(tooltip), false, GUTTER_TOOLTIP_GROUP); } else { controller.cancelTooltip(GUTTER_TOOLTIP_GROUP); diff --git a/source/com/intellij/openapi/editor/impl/EditorImpl.java b/source/com/intellij/openapi/editor/impl/EditorImpl.java index 36d51327d7d8..f62c6f9904ed 100644 --- a/source/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/source/com/intellij/openapi/editor/impl/EditorImpl.java @@ -4,6 +4,7 @@ import com.intellij.Patches; import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.hint.TooltipController; import com.intellij.codeInsight.hint.TooltipGroup; +import com.intellij.codeInsight.hint.DocumentFragmentTooltipRenderer; import com.intellij.ide.*; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.DataConstants; @@ -3481,7 +3482,7 @@ public class EditorImpl implements EditorEx { final Point p = SwingUtilities.convertPoint((Component)e.getSource(), e.getPoint(), getComponent().getRootPane().getLayeredPane()); - controller.showTooltip(EditorImpl.this, p, range, false, FOLDING_TOOLTIP_GROUP); + controller.showTooltip(EditorImpl.this, p, new DocumentFragmentTooltipRenderer(range), false, FOLDING_TOOLTIP_GROUP); } else { controller.cancelTooltip(FOLDING_TOOLTIP_GROUP); diff --git a/source/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java b/source/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java index 121f200afaeb..2f76a97ad766 100644 --- a/source/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java +++ b/source/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java @@ -11,11 +11,8 @@ package com.intellij.openapi.editor.impl; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.HighlightInfoComposite; -import com.intellij.codeInsight.hint.HintManager; -import com.intellij.codeInsight.hint.TooltipController; -import com.intellij.codeInsight.hint.TooltipGroup; +import com.intellij.codeInsight.hint.*; import com.intellij.ide.ui.LafManager; -import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.impl.ApplicationImpl; import com.intellij.openapi.command.CommandProcessor; @@ -119,15 +116,17 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark } } - 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(); + if (myCachedSortedHighlighters.size() != 0) { + 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; @@ -201,7 +200,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark if (e.getY() < buttonHeight && myErrorStripeRenderer != null) { String tooltipMessage = myErrorStripeRenderer.getTooltipMessage(); - showTooltip(e, tooltipMessage); + showTooltip(e, new LineTooltipRenderer(tooltipMessage)); return; } @@ -239,7 +238,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark } } - private void showTooltip(MouseEvent e, final Object tooltipObject) { + private void showTooltip(MouseEvent e, final TooltipRenderer tooltipObject) { if (tooltipObject != null) { final TooltipController tooltipController = HintManager.getInstance().getTooltipController(); tooltipController.showTooltipByMouseMove(myEditor, e, tooltipObject, @@ -374,7 +373,6 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark private int yEnd; private List markers = new ArrayList(); private TIntArrayList paintingEndOffsets = new TIntArrayList(); - private static final int MAX_TOOLTIP_LINES = 10; public ErrorMarkPile(final int yStart) { this.yStart = yStart; @@ -473,48 +471,41 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark if (!inside(e, width)) { return false; } + LineTooltipRenderer bigRenderer = null; List infos = new SmartList(); for (int i = 0; i < markers.size(); i++) { RangeHighlighter marker = markers.get(i); - if (marker.getErrorStripeTooltip() instanceof HighlightInfo) { - infos.add((HighlightInfo)marker.getErrorStripeTooltip()); + final Object tooltipObject = marker.getErrorStripeTooltip(); + if (tooltipObject == null) continue; + if (tooltipObject instanceof HighlightInfo) { + infos.add((HighlightInfo)tooltipObject); } - } - if (infos.size() == 0) { - RangeHighlighter marker = markers.get(0); - showTooltip(e, marker.getErrorStripeTooltip()); - } - else { - // need to show tooltips for multiple highlightinfos - final int oldSize = infos.size(); - int moreErrors = 0; - int moreWarnings = 0; - if (oldSize > MAX_TOOLTIP_LINES) { - for (int i = MAX_TOOLTIP_LINES; i < infos.size(); i++) { - HighlightInfo info = infos.get(i); - final HighlightSeverity severity = info.getSeverity(); - if (severity == HighlightSeverity.ERROR) { - moreErrors++; - } - else { - moreWarnings++; - } + else { + final String text = tooltipObject.toString(); + if (bigRenderer == null) { + bigRenderer = new LineTooltipRenderer(text); + } + else { + bigRenderer.addBelow(text); } - infos = infos.subList(0, MAX_TOOLTIP_LINES); } + } + if (infos.size() != 0) { + Collections.sort(infos, new Comparator() { + public int compare(final HighlightInfo o1, final HighlightInfo o2) { + return o1.getSeverity().compareTo(o2.getSeverity()); + } + }); final HighlightInfoComposite composite = new HighlightInfoComposite(infos); - if (moreErrors + moreWarnings != 0) { - String line = "   ..."; - if (moreErrors != 0) { - line += " and "+moreErrors + " more error" + (moreErrors == 1 ? "":"s"); - } - if (moreWarnings != 0) { - line += " and " + moreWarnings + " more warning" + (moreWarnings == 1 ? "" : "s"); - } - line += "..."; - composite.addToolTipLine(line); + if (bigRenderer == null) { + bigRenderer = new LineTooltipRenderer(composite.toolTip); } - showTooltip(e, composite); + else { + bigRenderer.addBelow(composite.toolTip); + } + } + if (bigRenderer != null) { + showTooltip(e, bigRenderer); } return true; } diff --git a/source/com/intellij/openapi/vcs/ex/LineStatusTracker.java b/source/com/intellij/openapi/vcs/ex/LineStatusTracker.java index 0f296c583f23..38f22a46e20f 100644 --- a/source/com/intellij/openapi/vcs/ex/LineStatusTracker.java +++ b/source/com/intellij/openapi/vcs/ex/LineStatusTracker.java @@ -109,7 +109,10 @@ public class LineStatusTracker implements EditorColorsListener { highlighter.setGreedyToRight(true); highlighter.setLineMarkerRenderer(createRenderer(range)); highlighter.setEditorFilter(MarkupEditorFilterFactory.createIsNotDiffFilter()); - highlighter.setErrorStripeTooltip("Line changed"); + final int line1 = myDocument.getLineNumber(first); + final int line2 = myDocument.getLineNumber(second); + final String tooltip = "Line" + (line1 == line2 ? " "+line1 : "s "+line1+"-"+line2) + " changed"; + highlighter.setErrorStripeTooltip(tooltip); return highlighter; } diff --git a/util/src/com/intellij/util/SmartList.java b/util/src/com/intellij/util/SmartList.java index b968c1d17d62..8d6c24b80eff 100644 --- a/util/src/com/intellij/util/SmartList.java +++ b/util/src/com/intellij/util/SmartList.java @@ -91,5 +91,12 @@ public class SmartList extends AbstractList { } return ArrayUtil.emptyArray(); } + + public E set(final int index, final E element) { + if (mySize <= 2) { + return myArray2[index] = element; + } + return myList.set(index, element); + } }