package org.intellij.plugins.markdown.structureView;
import com.intellij.ide.structureView.StructureViewBuilder;
import com.intellij.ide.structureView.StructureViewModel;
import com.intellij.ide.structureView.StructureViewModelBase;
import com.intellij.ide.structureView.TreeBasedStructureViewBuilder;
import com.intellij.lang.PsiStructureViewFactory;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiUtilCore;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static org.intellij.plugins.markdown.structureView.MarkdownStructureElement.PRESENTABLE_TYPES;
public class MarkdownStructureViewFactory implements PsiStructureViewFactory {
@Nullable
@Override
public StructureViewBuilder getStructureViewBuilder(@NotNull final PsiFile psiFile) {
return new TreeBasedStructureViewBuilder() {
@NotNull
@Override
public StructureViewModel createStructureViewModel(@Nullable Editor editor) {
return new MarkdownStructureViewModel(psiFile, editor);
}
};
}
private static class MarkdownStructureViewModel extends StructureViewModelBase {
public MarkdownStructureViewModel(@NotNull PsiFile psiFile, @Nullable Editor editor) {
super(psiFile, editor, new MarkdownStructureElement(psiFile));
}
@Nullable
@Override
protected Object findAcceptableElement(PsiElement element) {
// walk up the psi-tree until we find an element from the structure view
while (element != null && !PRESENTABLE_TYPES.contains(PsiUtilCore.getElementType(element))) {
IElementType parentType = PsiUtilCore.getElementType(element.getParent());
final PsiElement previous = element.getPrevSibling();
if (previous == null || !MarkdownStructureElement.TRANSPARENT_CONTAINERS.contains(parentType)) {
element = element.getParent();
}
else {
element = previous;
}
}
return element;
}
}
}