diff --git a/plugins/javaFX/src/META-INF/plugin.xml b/plugins/javaFX/src/META-INF/plugin.xml index 93d77ab56757..a4b9b29515f7 100644 --- a/plugins/javaFX/src/META-INF/plugin.xml +++ b/plugins/javaFX/src/META-INF/plugin.xml @@ -18,5 +18,6 @@ + diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java index 9941ea92b390..25b81c5ee022 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java @@ -15,6 +15,7 @@ */ package org.jetbrains.plugins.javaFX.fxml; +import com.intellij.codeInsight.AnnotationUtil; import com.intellij.lang.ASTNode; import com.intellij.lang.xml.XMLLanguage; import com.intellij.openapi.project.Project; @@ -246,4 +247,9 @@ public class JavaFxPsiUtil { } return null; } + + public static boolean isVisibleInFxml(PsiMember psiMember) { + return psiMember.hasModifierProperty(PsiModifier.PUBLIC) || + AnnotationUtil.isAnnotated(psiMember, JavaFxCommonClassNames.JAVAFX_FXML_ANNOTATION, false); + } } diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/JavaFxRelatedItemLineMarkerProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/JavaFxRelatedItemLineMarkerProvider.java new file mode 100644 index 000000000000..361a31651445 --- /dev/null +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/JavaFxRelatedItemLineMarkerProvider.java @@ -0,0 +1,108 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.javaFX.fxml.codeInsight; + +import com.intellij.codeHighlighting.Pass; +import com.intellij.codeInsight.daemon.GutterIconNavigationHandler; +import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo; +import com.intellij.codeInsight.daemon.RelatedItemLineMarkerProvider; +import com.intellij.codeInsight.navigation.NavigationUtil; +import com.intellij.icons.AllIcons; +import com.intellij.navigation.GotoRelatedItem; +import com.intellij.openapi.editor.markup.GutterIconRenderer; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.psi.*; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.xml.XmlAttribute; +import com.intellij.psi.xml.XmlAttributeValue; +import com.intellij.ui.awt.RelativePoint; +import com.intellij.util.CommonProcessors; +import com.intellij.util.ConstantFunction; +import com.intellij.util.Function; +import com.intellij.util.Processor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory; +import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil; + +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collection; + +/** + * User: anna + */ +public class JavaFxRelatedItemLineMarkerProvider extends RelatedItemLineMarkerProvider { + @Override + protected void collectNavigationMarkers(@NotNull PsiElement element, final Collection result) { + if (element instanceof PsiField) { + final PsiField field = (PsiField)element; + if (JavaFxPsiUtil.isVisibleInFxml(field) && !field.hasModifierProperty(PsiModifier.STATIC)) { + final PsiClass containingClass = field.getContainingClass(); + if (containingClass != null && containingClass.hasModifierProperty(PsiModifier.PUBLIC)) { + final ArrayList targets = new ArrayList(); + collectTargets(element, targets, new Function() { + @Override + public GotoRelatedItem fun(PsiElement element) { + return new GotoRelatedItem(element); + } + }, true); + if (targets.isEmpty()) return; + + result.add(new RelatedItemLineMarkerInfo(field, field.getNameIdentifier().getTextRange(), + AllIcons.FileTypes.Xml, Pass.UPDATE_OVERRIDEN_MARKERS, null, + new JavaFXIdIconNavigationHandler(), GutterIconRenderer.Alignment.LEFT, + targets)); + } + } + } + } + + private static void collectTargets(PsiElement element, final ArrayList targets, final Function fun, final boolean stopAtFirst) { + ReferencesSearch.search(element).forEach(new Processor() { + @Override + public boolean process(PsiReference reference) { + final PsiElement referenceElement = reference.getElement(); + if (referenceElement == null) return true; + if (!(referenceElement instanceof XmlAttributeValue)) return true; + final XmlAttributeValue attributeValue = (XmlAttributeValue)referenceElement; + final PsiElement parent = attributeValue.getParent(); + if (!(parent instanceof XmlAttribute)) return true; + final PsiFile containingFile = referenceElement.getContainingFile(); + if (containingFile == null) return true; + if (JavaFxFileTypeFactory.isFxml(containingFile)) { + targets.add(fun.fun(parent)); + if (stopAtFirst) return false; + } + return true; + } + }); + } + + private static class JavaFXIdIconNavigationHandler implements GutterIconNavigationHandler { + @Override + public void navigate(MouseEvent e, PsiField field) { + final ArrayList relatedItems = new ArrayList(); + collectTargets(field, relatedItems, Function.ID, false); + if (relatedItems.size() == 1) { + NavigationUtil.activateFileWithPsiElement(relatedItems.get(0)); + return; + } + final JBPopup popup = NavigationUtil + .getPsiElementPopup(relatedItems.toArray(new PsiElement[relatedItems.size()]), "Choose component with fx:id " + field.getName() + ""); + popup.show(new RelativePoint(e)); + } + } +} diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java index 979b48889cc0..bc8e89e721e4 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java @@ -59,8 +59,7 @@ public class JavaFxAnnotator implements Annotator { for (PsiReference reference : references) { final PsiElement resolve = reference.resolve(); if (resolve instanceof PsiMember) { - if (!((PsiMember)resolve).hasModifierProperty(PsiModifier.PUBLIC) && - !AnnotationUtil.isAnnotated((PsiMember)resolve, Collections.singleton(JavaFxCommonClassNames.JAVAFX_FXML_ANNOTATION))) { + if (!JavaFxPsiUtil.isVisibleInFxml((PsiMember)resolve)) { final String symbolPresentation = "'" + SymbolPresentationUtil.getSymbolPresentableText(resolve) + "'"; final Annotation annotation = holder.createErrorAnnotation(element, symbolPresentation + (resolve instanceof PsiClass ? " should be public" : " should be public or annotated with @FXML")); diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java index 403e1be2df95..9185b75fc511 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java @@ -15,14 +15,13 @@ */ package org.jetbrains.plugins.javaFX.fxml.refs; -import com.intellij.codeInsight.AnnotationUtil; import com.intellij.psi.*; import com.intellij.psi.xml.XmlAttributeValue; import com.intellij.util.ArrayUtil; import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames; +import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil; import java.util.ArrayList; import java.util.List; @@ -51,7 +50,7 @@ class JavaFxFieldIdReferenceProvider extends JavaFxControllerBasedReferenceProvi final PsiField[] fields = aClass.getFields(); for (PsiField psiField : fields) { if (!psiField.hasModifierProperty(PsiModifier.STATIC)) { - if (psiField.hasModifierProperty(PsiModifier.PUBLIC) || AnnotationUtil.isAnnotated(psiField, JavaFxCommonClassNames.JAVAFX_FXML_ANNOTATION, false)) { + if (JavaFxPsiUtil.isVisibleInFxml(psiField)) { fieldsToSuggest.add(psiField); } }