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
4 comments
Comment actions Permalink

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
Comment actions Permalink

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
Comment actions Permalink

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
Comment actions Permalink

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.