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
0
4 comments

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.

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;
}
}

---
Original message URL:
http://devnet.jetbrains.net/message/5305777#5305777


--
Dmitry Jemerov
Development Lead
JetBrains, Inc.
http://www.jetbrains.com/
"Develop with Pleasure!"


0
Avatar
Permanently deleted user

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().

here's how I create my nodes:


  private Collection<AbstractTreeNode> filterIndividualRules(ViewSettings settings, Collection<AbstractTreeNode> children) {
    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!");
  }

}
0
Avatar
Permanently deleted user

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:

  @Override
  public boolean canNavigateToSource() {
    return true;
  }

  @Override
  public void navigate(boolean requestFocus) {
    System.out.println("this is NOT printed!");
  }
0
Avatar
Permanently deleted user

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");
  }

0

Please sign in to leave a comment.