/* * Copyright 2010 The WicketForge-Team * * 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 wicketforge.psi.hierarchy; import com.intellij.ide.structureView.StructureViewTreeElement; import com.intellij.ide.structureView.TextEditorBasedStructureViewModel; import com.intellij.ide.util.treeView.smartTree.TreeElement; import com.intellij.navigation.ItemPresentation; import com.intellij.psi.PsiCallExpression; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiJavaFile; import com.intellij.util.PsiNavigateUtil; import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; import wicketforge.util.WicketPsiUtil; import java.util.List; /** */ public class ClassStructureTreeModel extends TextEditorBasedStructureViewModel { private StructureViewTreeElement root; private static final TreeElement[] EMPTY_TREE_ELEMENTS = new TreeElement[0]; public ClassStructureTreeModel(@NotNull PsiJavaFile psiJavaFile) { super(psiJavaFile); root = new JavaFileTreeElement(psiJavaFile); } @Override @NotNull public StructureViewTreeElement getRoot() { return root; } @Override protected boolean isSuitable(PsiElement element) { if (element instanceof PsiCallExpression) { for (TreeElement treeElement : getRoot().getChildren()) { if (treeElement instanceof ClassTreeElement) { return ((ClassTreeElement) treeElement).classWicketIdReferences.getNewComponentItem((PsiCallExpression) element) != null; } } } else if (element instanceof PsiClass) { return WicketPsiUtil.isWicketComponentWithAssociatedMarkup((PsiClass) element); } return super.isSuitable(element); } private static class JavaFileTreeElement implements StructureViewTreeElement { private PsiJavaFile psiJavaFile; private JavaFileTreeElement(@NotNull PsiJavaFile psiJavaFile) { this.psiJavaFile = psiJavaFile; } @Override public Object getValue() { return psiJavaFile; } @Override public void navigate(boolean requestFocus) { psiJavaFile.navigate(requestFocus); } @Override public boolean canNavigate() { return psiJavaFile.canNavigate(); } @Override public boolean canNavigateToSource() { return psiJavaFile.canNavigateToSource(); } @NotNull @Override public ItemPresentation getPresentation() { return psiJavaFile.getPresentation(); } private TreeElement[] children; @NotNull @Override public TreeElement[] getChildren() { if (children == null) { List<TreeElement> list = new SmartList<TreeElement>(); for (PsiClass psiClass : psiJavaFile.getClasses()) { if (WicketPsiUtil.isWicketComponentWithAssociatedMarkup(psiClass)) { list.add(new ClassTreeElement(psiClass, ClassWicketIdReferences.build(psiClass, false))); } } children = list.isEmpty() ? EMPTY_TREE_ELEMENTS : list.toArray(new TreeElement[list.size()]); } return children; } } private static class ClassTreeElement implements StructureViewTreeElement { private TreeElement[] children; final ClassWicketIdReferences classWicketIdReferences; final PsiClass psiClass; private ClassTreeElement(@NotNull PsiClass psiClass, @NotNull ClassWicketIdReferences classWicketIdReferences) { this.psiClass = psiClass; this.classWicketIdReferences = classWicketIdReferences; } @Override public Object getValue() { return psiClass; } @Override public void navigate(boolean requestFocus) { psiClass.navigate(requestFocus); } @Override public boolean canNavigate() { return psiClass.canNavigate(); } @Override public boolean canNavigateToSource() { return psiClass.canNavigateToSource(); } @NotNull @Override public ItemPresentation getPresentation() { return psiClass.getPresentation(); } @NotNull @Override public TreeElement[] getChildren() { if (children == null) { List<TreeElement> list = new SmartList<TreeElement>(); List<PsiCallExpression> addedComponents = classWicketIdReferences.getAdded(psiClass); if (addedComponents != null) { for (PsiCallExpression addedComponent : addedComponents) { list.add(new WicketIdTreeElement(addedComponent)); } } for (PsiClass aClass : psiClass.getAllInnerClasses()) { if (classWicketIdReferences.containsClass(aClass) && WicketPsiUtil.isWicketComponentWithAssociatedMarkup(aClass)) { list.add(new ClassTreeElement(aClass, classWicketIdReferences)); } } children = list.isEmpty() ? EMPTY_TREE_ELEMENTS : list.toArray(new TreeElement[list.size()]); } return children; } private class WicketIdTreeElement implements StructureViewTreeElement { private TreeElement[] children; private final PsiCallExpression psiElement; private final ClassWicketIdNewComponentItem newComponentItem; private WicketIdTreeElement(PsiCallExpression psiElement) { this.psiElement = psiElement; this.newComponentItem = classWicketIdReferences.getNewComponentItem(psiElement); } @Override public Object getValue() { return psiElement; } @Override public void navigate(boolean requestFocus) { PsiNavigateUtil.navigate(newComponentItem != null ? newComponentItem.getWicketIdExpression() : psiElement); } @Override public boolean canNavigate() { return true; } @Override public boolean canNavigateToSource() { return true; } @NotNull @Override public ItemPresentation getPresentation() { return newComponentItem; } @NotNull @Override public TreeElement[] getChildren() { if (children == null) { List<PsiCallExpression> addedComponents = classWicketIdReferences.getAdded(psiElement); if (addedComponents != null) { children = new TreeElement[addedComponents.size()]; for (int i = 0, addedComponentsSize = addedComponents.size(); i < addedComponentsSize; i++) { PsiCallExpression addedComponent = addedComponents.get(i); children[i] = new WicketIdTreeElement(addedComponent); } } else { children = EMPTY_TREE_ELEMENTS; } } return children; } } } }