| package org.jetbrains.android; |
| |
| import com.intellij.codeHighlighting.Pass; |
| import com.intellij.codeInsight.daemon.GutterIconNavigationHandler; |
| import com.intellij.codeInsight.daemon.LineMarkerInfo; |
| import com.intellij.codeInsight.daemon.LineMarkerProvider; |
| import com.intellij.codeInsight.navigation.NavigationUtil; |
| import com.intellij.icons.AllIcons; |
| import com.intellij.navigation.GotoRelatedItem; |
| import com.intellij.openapi.util.Computable; |
| import com.intellij.psi.PsiClass; |
| import com.intellij.psi.PsiElement; |
| import com.intellij.psi.PsiIdentifier; |
| import com.intellij.psi.PsiJavaFile; |
| import com.intellij.psi.xml.XmlFile; |
| import com.intellij.psi.xml.XmlTag; |
| import com.intellij.ui.awt.RelativePoint; |
| import com.intellij.util.ConstantFunction; |
| import org.jetbrains.android.facet.AndroidFacet; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.awt.event.MouseEvent; |
| import java.util.Collection; |
| import java.util.List; |
| |
| /** |
| * @author Eugene.Kudelevsky |
| */ |
| public class AndroidLineMarkerProvider implements LineMarkerProvider { |
| |
| @Override |
| public void collectSlowLineMarkers(@NotNull List<PsiElement> elements, @NotNull Collection<LineMarkerInfo> result) { |
| for (PsiElement element : elements) { |
| final LineMarkerInfo info = doGetLineMarkerInfo(element); |
| |
| if (info != null) { |
| result.add(info); |
| } |
| } |
| } |
| |
| @Nullable |
| @Override |
| public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element) { |
| return null; |
| } |
| |
| private static LineMarkerInfo doGetLineMarkerInfo(PsiElement element) { |
| final MyMarkerInfo info = getMarkerInfo(element); |
| |
| if (info == null) { |
| return null; |
| } |
| final PsiElement anchor = info.myElement; |
| final String tooltip = info.myTooltip; |
| |
| return new LineMarkerInfo<PsiElement>( |
| anchor, anchor.getTextOffset(), info.myIcon, Pass.UPDATE_OVERRIDEN_MARKERS, |
| new ConstantFunction<PsiElement, String>(tooltip), new MyNavigationHandler(info)); |
| } |
| |
| @Nullable |
| private static MyMarkerInfo getMarkerInfo(@NotNull PsiElement element) { |
| if (!(element instanceof XmlFile) && !(element instanceof PsiJavaFile)) { |
| return null; |
| } |
| final AndroidFacet facet = AndroidFacet.getInstance(element); |
| |
| if (facet == null) { |
| return null; |
| } |
| |
| if (element instanceof PsiJavaFile) { |
| final PsiClass[] classes = ((PsiJavaFile)element).getClasses(); |
| |
| if (classes.length == 1) { |
| final PsiClass aClass = classes[0]; |
| final PsiIdentifier nameIdentifier = aClass.getNameIdentifier(); |
| |
| if (nameIdentifier != null) { |
| final Computable<List<GotoRelatedItem>> computable = AndroidGotoRelatedProvider.getLazyItemsForClass(aClass, facet, true); |
| return computable != null ? new MyMarkerInfo(nameIdentifier, computable, "Related XML file", AllIcons.FileTypes.Xml) : null; |
| } |
| } |
| } |
| else { |
| final XmlTag rootTag = ((XmlFile)element).getRootTag(); |
| final Computable<List<GotoRelatedItem>> computable = AndroidGotoRelatedProvider.getLazyItemsForXmlFile((XmlFile)element, facet); |
| return computable != null ? new MyMarkerInfo(rootTag != null ? rootTag : element, computable, |
| "Related context Java file", AllIcons.Nodes.Class) : null; |
| } |
| return null; |
| } |
| |
| private static class MyMarkerInfo { |
| final PsiElement myElement; |
| final String myTooltip; |
| final Icon myIcon; |
| private final Computable<List<GotoRelatedItem>> myComputable; |
| |
| private MyMarkerInfo(@NotNull PsiElement element, |
| @NotNull Computable<List<GotoRelatedItem>> computable, |
| @NotNull String tooltip, |
| @NotNull Icon icon) { |
| myElement = element; |
| myComputable = computable; |
| myTooltip = tooltip; |
| myIcon = icon; |
| } |
| |
| public List<GotoRelatedItem> compute() { |
| return myComputable.compute(); |
| } |
| } |
| |
| public static class MyNavigationHandler implements GutterIconNavigationHandler<PsiElement> { |
| private final MyMarkerInfo myInfo; |
| |
| private MyNavigationHandler(MyMarkerInfo info) { |
| myInfo = info; |
| } |
| |
| @Override |
| public void navigate(MouseEvent e, PsiElement elt) { |
| final List<GotoRelatedItem> items = doComputeItems(); |
| |
| if (items.size() == 1) { |
| items.get(0).navigate(); |
| } |
| else { |
| NavigationUtil.getRelatedItemsPopup(items, "Go to Related Files").show(new RelativePoint(e)); |
| } |
| } |
| |
| @NotNull |
| public List<GotoRelatedItem> doComputeItems() { |
| return myInfo.compute(); |
| } |
| } |
| } |