my custom node is not recognized as a file in Project View
I created:
class RulesetTreeNode extends ProjectViewNode;
class GosuRulesTreeStructureProvider extends ClassesTreeStructureProvider
registered in plugin.xml:
<treeStructureProvider id="someid" implementation="gw.plugin.ij.project.GosuRulesTreeStructureProvider"/>
this tree provider replaces certain directories in Project View with "fake" nodes shown on the screenshot (see "set1..", "set2.."...)
now I need to open my editor when user double-clicks on this "fake node".
I created
class RulesEditorProvider implements ApplicationComponent, FileEditorProvider, DumbAware
@Override
public boolean accept(@NotNull Project project, @NotNull
VirtualFile virtualFile) {
System.out.println("checking " + virtualFile.getName());
Boolean flag = virtualFile.getUserData(GosuRulesTreeStructureProvider.KEY_RULE_SET);
return flag != null && flag;
}
and
class RuleSetEditor implements FileEditor
registered the editor:
<fileEditorProvider id="rules_editor_id" implementation="gw.plugin.ij.editors.RulesEditorProvider"/>
this editor works fine if I change accept() method to return true for some files (say, for "*.myext" files).
now, the accept() method is not even called when I click on my "fake" nodes, so I think IDEA probably does not recognize these nodes as "files" (they original nodes were actually directories on disk, not regular files).
So, how do I open my editor for these "fake" nodes?
import com.intellij.ide.projectView.PresentationData;
import com.intellij.ide.projectView.ProjectViewNode;
import com.intellij.ide.projectView.ViewSettings;
import com.intellij.ide.projectView.impl.nodes.BasePsiMemberNode;
import com.intellij.ide.projectView.impl.nodes.ClassTreeNode;
import com.intellij.ide.projectView.impl.nodes.PsiFileNode;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import gw.plugin.ij.icons.GosuIcons;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
public class RulesetTreeNode extends ProjectViewNode {
private VirtualFile file;
private String name;
private Collection<? extends AbstractTreeNode> children;
public RulesetTreeNode(Project myProject, VirtualFile f, PsiElement classOwner, ViewSettings settings, String name, Collection<? extends AbstractTreeNode> children) {
super(myProject, classOwner, settings);
file = f;
this.name = name;
this.children = children;
}
@Override
public VirtualFile getVirtualFile() {
return file;
}
@Override
public boolean contains(@NotNull VirtualFile file) {
System.out.println("contains? " + file.getName());
return false; //To change body of implemented methods use File | Settings | File Templates.
}
@NotNull
@Override
public Collection<? extends AbstractTreeNode> getChildren() {
return children;
}
@Override
protected void update(PresentationData presentation) {
// set the label for this node visible in Project View
presentation.setPresentableText(name);
presentation.setClosedIcon(GosuIcons.FILE_RULE_SET);
presentation.setOpenIcon(GosuIcons.FILE_RULE_SET);
}
@Override
public String getTitle() {
return name;
}
}
Attachment(s):
rules.PNG
Please sign in to leave a comment.
Hello Alexey,
The Value that you set for the ProjectViewNode (classOwner in your case)
needs to implement the Navigatable interface. The navigate() method will
be called when you double-click on the node or press F4.
--
Dmitry Jemerov
Development Lead
JetBrains, Inc.
http://www.jetbrains.com/
"Develop with Pleasure!"
I tried using "navigate()" method for the "classOwner", but it's not called... I call ProjectViewNode() constructor with MyFile instance, which extends PsiJavaDirectoryImpl and overrides navigate() method. I set a breakpoint in navigate() and canNavigateToSource() -they are not called. btw, I always return TRUE from canNavigateToSource().
ArrayList<AbstractTreeNode> result = new ArrayList<AbstractTreeNode>();
for (final AbstractTreeNode child : children) {
Object o = child.getValue();
if (o instanceof PsiDirectory) {
PsiDirectory dir = (PsiDirectory) o;
int numberOfRules = countRules(dir);
String newName = dir.getName() + " (" + numberOfRules + " sets)";
VirtualDirectoryImpl f = (VirtualDirectoryImpl) dir.getVirtualFile();
f.putUserData(KEY_RULE_SET, true);
result.add(new RulesetTreeNode(myProject, dir, settings, newName, new ArrayList<AbstractTreeNode>()));
}
}
return result;
}
--------------------and here's the updated node class---------
package gw.plugin.ij.project;
import com.intellij.ide.projectView.PresentationData;
import com.intellij.ide.projectView.ProjectViewNode;
import com.intellij.ide.projectView.ViewSettings;
import com.intellij.ide.projectView.impl.nodes.BasePsiMemberNode;
import com.intellij.ide.projectView.impl.nodes.ClassTreeNode;
import com.intellij.ide.projectView.impl.nodes.PsiFileNode;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl;
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileImpl;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.psi.impl.file.PsiJavaDirectoryImpl;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
public class RulesetTreeNode extends ProjectViewNode {
// private VirtualFile file;
private String name;
private Collection<? extends AbstractTreeNode> children;
public RulesetTreeNode(Project myProject, PsiElement element, ViewSettings settings, String name, Collection<? extends AbstractTreeNode> children) {
super(myProject, new MyFile(element), settings);
// System.out.println(f.getClass());
// file = f;
this.name = name;
this.children = children;
}
@Override
public VirtualFile getVirtualFile() {
return null;
}
@Override
public boolean contains(@NotNull VirtualFile file) {
return false;
}
@NotNull
@Override
public Collection<? extends AbstractTreeNode> getChildren() {
return children;
}
@Override
protected void update(PresentationData presentation) {
// set the label for this node visible in Project View
presentation.setPresentableText(name);
presentation.setClosedIcon(IconLoader.getIcon("/modules/webRoot.png"));
presentation.setOpenIcon(IconLoader.getIcon("/modules/webRoot.png"));
}
@Override
public String getTitle() {
return name;
}
}
class MyFile extends PsiJavaDirectoryImpl {
public MyFile(PsiManagerImpl manager, VirtualFile file) {
super(manager, file);
}
public MyFile(PsiElement element) {
this((PsiManagerImpl) element.getManager(), ((PsiDirectory)element).getVirtualFile());
}
@Override
public boolean canNavigateToSource() {
return true;
}
@Override
public void navigate(boolean requestFocus) {
System.out.println("this is NOT printed!");
}
}
OK, I see there was "NPE in "myFile.toString() evaluation", so I had to override this method in MyFile class:
@Override
public String toString() {
return name;
}
but even now these methods are not even called:
public boolean canNavigateToSource() {
return true;
}
@Override
public void navigate(boolean requestFocus) {
System.out.println("this is NOT printed!");
}
OK, Solved: needed to add these methods to my RulesetTreeNode class itself:
@Override
public boolean canNavigateToSource() {
return true;
}
@Override
public boolean canNavigate() {
return true;
}
@Override
public void navigate(boolean requestFocus) {
Messages.showInfoMessage("Start your Rules Editor here", "Title");
}