2 * Copyright 2000-2011 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 package com.intellij.codeInsight.daemon.impl;
22 import com.intellij.codeInsight.daemon.DaemonBundle;
23 import com.intellij.codeInsight.daemon.impl.actions.ShowErrorDescriptionAction;
24 import com.intellij.codeInsight.hint.LineTooltipRenderer;
25 import com.intellij.codeInsight.hint.TooltipLinkHandlerEP;
26 import com.intellij.codeInsight.hint.TooltipRenderer;
27 import com.intellij.openapi.editor.Editor;
28 import com.intellij.openapi.editor.ex.ErrorStripTooltipRendererProvider;
29 import com.intellij.openapi.editor.impl.TrafficTooltipRenderer;
30 import com.intellij.openapi.editor.markup.RangeHighlighter;
31 import com.intellij.openapi.project.Project;
32 import com.intellij.openapi.util.text.StringUtil;
33 import com.intellij.util.SmartList;
34 import com.intellij.util.containers.ContainerUtil;
35 import com.intellij.util.ui.UIUtil;
36 import gnu.trove.THashSet;
37 import org.jetbrains.annotations.NonNls;
38 import org.jetbrains.annotations.NotNull;
39 import org.jetbrains.annotations.Nullable;
42 import java.util.Collection;
43 import java.util.Comparator;
44 import java.util.List;
45 import java.util.regex.Matcher;
46 import java.util.regex.Pattern;
48 public class DaemonTooltipRendererProvider implements ErrorStripTooltipRendererProvider {
49 private final Project myProject;
51 public DaemonTooltipRendererProvider(final Project project) {
56 public TooltipRenderer calcTooltipRenderer(@NotNull final Collection<RangeHighlighter> highlighters) {
57 LineTooltipRenderer bigRenderer = null;
58 List<HighlightInfo> infos = new SmartList<HighlightInfo>();
59 Collection<String> tooltips = new THashSet<String>(); //do not show same tooltip twice
60 for (RangeHighlighter marker : highlighters) {
61 final Object tooltipObject = marker.getErrorStripeTooltip();
62 if (tooltipObject == null) continue;
63 if (tooltipObject instanceof HighlightInfo) {
64 HighlightInfo info = (HighlightInfo)tooltipObject;
65 if (info.toolTip != null && tooltips.add(info.toolTip)) {
70 final String text = tooltipObject.toString();
71 if (tooltips.add(text)) {
72 if (bigRenderer == null) {
73 bigRenderer = new MyRenderer(text, new Object[] {highlighters});
76 bigRenderer.addBelow(text);
81 if (!infos.isEmpty()) {
83 ContainerUtil.quickSort(infos, new Comparator<HighlightInfo>() {
85 public int compare(final HighlightInfo o1, final HighlightInfo o2) {
86 int i = SeverityRegistrar.getInstance(myProject).compare(o2.getSeverity(), o1.getSeverity());
88 return o1.toolTip.compareTo(o2.toolTip);
91 final HighlightInfoComposite composite = new HighlightInfoComposite(infos);
92 if (bigRenderer == null) {
93 bigRenderer = new MyRenderer(UIUtil.convertSpace2Nbsp(composite.toolTip), new Object[] {highlighters});
96 final LineTooltipRenderer renderer = new MyRenderer(UIUtil.convertSpace2Nbsp(composite.toolTip), new Object[] {highlighters});
97 renderer.addBelow(bigRenderer.getText());
98 bigRenderer = renderer;
105 public TooltipRenderer calcTooltipRenderer(@NotNull final String text) {
106 return new MyRenderer(text, new Object[] {text});
110 public TooltipRenderer calcTooltipRenderer(@NotNull final String text, final int width) {
111 return new MyRenderer(text, width, new Object[] {text});
115 public TrafficTooltipRenderer createTrafficTooltipRenderer(Runnable onHide, Editor editor) {
116 return new TrafficTooltipRendererImpl(onHide, editor);
119 private static class MyRenderer extends LineTooltipRenderer {
120 public MyRenderer(final String text, Object[] comparable) {
121 super(text, comparable);
124 public MyRenderer(final String text, final int width, Object[] comparable) {
125 super(text, width, comparable);
129 protected void onHide(final JComponent contentComponent) {
130 ShowErrorDescriptionAction.rememberCurrentWidth(contentComponent.getWidth());
134 protected boolean dressDescription(@NotNull final Editor editor) {
135 final String[] problems = UIUtil.getHtmlBody(myText).split(BORDER_LINE);
137 for (String problem : problems) {
138 final String ref = getLinkRef(problem);
140 String description = TooltipLinkHandlerEP.getDescription(ref, editor);
141 if (description != null) {
142 final Pattern pattern = Pattern.compile(".*Use.*(the (panel|checkbox|checkboxes|field|button|controls).*below).*", Pattern.DOTALL);
143 final Matcher matcher = pattern.matcher(description);
144 int startFindIdx = 0;
145 while (matcher.find(startFindIdx)) {
146 final int end = matcher.end(1);
148 description = description.substring(0, matcher.start(1)) + " inspection settings " + description.substring(end);
150 text += UIUtil.getHtmlBody(problem).replace(DaemonBundle.message("inspection.extended.description"),
151 DaemonBundle.message("inspection.collapse.description")) +
152 BORDER_LINE + UIUtil.getHtmlBody(description) + BORDER_LINE;
156 if (text.length() > 0) { //otherwise do not change anything
157 myText = "<html><body>" + StringUtil.trimEnd(text, BORDER_LINE) + "</body></html>";
164 private static String getLinkRef(@NonNls String text) {
165 final String linkWithRef = "<a href=\"";
166 final int linkStartIdx = text.indexOf(linkWithRef);
167 if (linkStartIdx >= 0) {
168 final String ref = text.substring(linkStartIdx + linkWithRef.length());
169 final int quoteIdx = ref.indexOf('"');
171 return ref.substring(0, quoteIdx);
178 protected void stripDescription() {
179 final String[] problems = UIUtil.getHtmlBody(myText).split(BORDER_LINE);
180 myText = "<html><body>";
181 for (int i = 0; i < problems.length; i++) {
182 final String problem = problems[i];
184 myText += UIUtil.getHtmlBody(problem).replace(DaemonBundle.message("inspection.collapse.description"),
185 DaemonBundle.message("inspection.extended.description")) + BORDER_LINE;
188 myText = StringUtil.trimEnd(myText, BORDER_LINE) + "</body></html>";
192 protected LineTooltipRenderer createRenderer(final String text, final int width) {
193 return new MyRenderer(text, width, getEqualityObjects());