560879fd906740e2ca10b2feefe08f2870375f16
[idea/community.git] / platform / lang-api / src / com / intellij / codeInsight / daemon / LineMarkerInfo.java
1 /*
2  * Copyright 2000-2015 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package com.intellij.codeInsight.daemon;
18
19 import com.intellij.openapi.actionSystem.AnAction;
20 import com.intellij.openapi.editor.markup.GutterIconRenderer;
21 import com.intellij.openapi.editor.markup.RangeHighlighter;
22 import com.intellij.openapi.editor.markup.SeparatorPlacement;
23 import com.intellij.openapi.project.IndexNotReadyException;
24 import com.intellij.openapi.util.Comparing;
25 import com.intellij.openapi.util.TextRange;
26 import com.intellij.psi.PsiElement;
27 import com.intellij.util.Function;
28 import org.jetbrains.annotations.NotNull;
29 import org.jetbrains.annotations.Nullable;
30
31 import javax.swing.*;
32 import java.awt.*;
33 import java.lang.ref.WeakReference;
34
35 public class LineMarkerInfo<T extends PsiElement> {
36   protected final Icon myIcon;
37   private final WeakReference<T> elementRef;
38   public final int startOffset;
39   public final int endOffset;
40   public Color separatorColor;
41   public SeparatorPlacement separatorPlacement;
42   public RangeHighlighter highlighter;
43
44   public final int updatePass;
45   @Nullable private final Function<? super T, String> myTooltipProvider;
46   private AnAction myNavigateAction = new NavigateAction<>(this);
47   @NotNull private final GutterIconRenderer.Alignment myIconAlignment;
48   @Nullable private final GutterIconNavigationHandler<T> myNavigationHandler;
49
50   /**
51    * Creates a line marker info for the element.
52    * @param element         the element for which the line marker is created.
53    * @param startOffset     the offset (relative to beginning of file) with which the marker is associated
54    * @param icon            the icon to show in the gutter for the line marker
55    * @param updatePass      the ID of the daemon pass during which the marker should be recalculated
56    * @param tooltipProvider the callback to calculate the tooltip for the gutter icon
57    * @param navHandler      the handler executed when the gutter icon is clicked
58    */
59   public LineMarkerInfo(@NotNull T element,
60                         @NotNull TextRange range,
61                         Icon icon,
62                         int updatePass,
63                         @Nullable Function<? super T, String> tooltipProvider,
64                         @Nullable GutterIconNavigationHandler<T> navHandler,
65                         @NotNull GutterIconRenderer.Alignment alignment) {
66     myIcon = icon;
67     myTooltipProvider = tooltipProvider;
68     myIconAlignment = alignment;
69     elementRef = new WeakReference<>(element);
70     myNavigationHandler = navHandler;
71     startOffset = range.getStartOffset();
72     endOffset = range.getEndOffset();
73     this.updatePass = 11; //Pass.LINE_MARKERS;
74   }
75
76   /**
77    * @deprecated use {@link LineMarkerInfo#LineMarkerInfo(PsiElement, TextRange, Icon, int, Function, GutterIconNavigationHandler, GutterIconRenderer.Alignment)} instead
78    */
79   public LineMarkerInfo(@NotNull T element,
80                         int startOffset,
81                         Icon icon,
82                         int updatePass,
83                         @Nullable Function<? super T, String> tooltipProvider,
84                         @Nullable GutterIconNavigationHandler<T> navHandler,
85                         @NotNull GutterIconRenderer.Alignment alignment) {
86     this(element, new TextRange(startOffset, startOffset), icon, updatePass, tooltipProvider, navHandler, alignment);
87   }
88
89   /**
90    * @deprecated use {@link LineMarkerInfo#LineMarkerInfo(PsiElement, TextRange, Icon, int, Function, GutterIconNavigationHandler, GutterIconRenderer.Alignment)} instead
91    */
92   public LineMarkerInfo(@NotNull T element,
93                         int startOffset,
94                         Icon icon,
95                         int updatePass,
96                         @Nullable Function<? super T, String> tooltipProvider,
97                         @Nullable GutterIconNavigationHandler<T> navHandler) {
98     this(element, startOffset, icon, updatePass, tooltipProvider, navHandler, GutterIconRenderer.Alignment.RIGHT);
99   }
100
101   @Nullable
102   public GutterIconRenderer createGutterRenderer() {
103     if (myIcon == null) return null;
104     return new LineMarkerGutterIconRenderer<>(this);
105   }
106
107   @Nullable
108   public String getLineMarkerTooltip() {
109     if (myTooltipProvider == null) return null;
110     T element = getElement();
111     return element == null || !element.isValid() ? null : myTooltipProvider.fun(element);
112   }
113
114   @Nullable
115   public T getElement() {
116     return elementRef.get();
117   }
118
119   void setNavigateAction(@NotNull  AnAction navigateAction) {
120     myNavigateAction = navigateAction;
121   }
122
123   @Nullable
124   public GutterIconNavigationHandler<T> getNavigationHandler() {
125     return myNavigationHandler;
126   }
127
128   public static class LineMarkerGutterIconRenderer<T extends PsiElement> extends GutterIconRenderer {
129     private final LineMarkerInfo<T> myInfo;
130
131     public LineMarkerGutterIconRenderer(@NotNull LineMarkerInfo<T> info) {
132       myInfo = info;
133     }
134
135     public LineMarkerInfo<T> getLineMarkerInfo() {
136       return myInfo;
137     }
138
139     @Override
140     @NotNull
141     public Icon getIcon() {
142       return myInfo.myIcon;
143     }
144
145     @Override
146     public AnAction getClickAction() {
147       return myInfo.myNavigateAction;
148     }
149
150     @Override
151     public boolean isNavigateAction() {
152       return myInfo.myNavigationHandler != null;
153     }
154
155     @Override
156     public String getTooltipText() {
157       try {
158         return myInfo.getLineMarkerTooltip();
159       }
160       catch (IndexNotReadyException ignored) {
161         return null;
162       }
163     }
164
165     @NotNull
166     @Override
167     public Alignment getAlignment() {
168       return myInfo.myIconAlignment;
169     }
170
171     protected boolean looksTheSameAs(@NotNull LineMarkerGutterIconRenderer renderer) {
172       return
173         myInfo.getElement() != null &&
174         renderer.myInfo.getElement() != null &&
175         myInfo.getElement() == renderer.myInfo.getElement() &&
176         Comparing.equal(myInfo.myTooltipProvider, renderer.myInfo.myTooltipProvider) &&
177         Comparing.equal(myInfo.myIcon, renderer.myInfo.myIcon);
178     }
179
180     @Override
181     public boolean equals(Object obj) {
182       return obj instanceof LineMarkerGutterIconRenderer && looksTheSameAs((LineMarkerGutterIconRenderer)obj);
183     }
184
185     @Override
186     public int hashCode() {
187       T element = myInfo.getElement();
188       return element == null ? 0 : element.hashCode();
189     }
190   }
191
192   @Override
193   public String toString() {
194     return "("+startOffset+","+endOffset+") -> "+elementRef.get();
195   }
196 }