public void actionPerformed(final AnActionEvent e) {
   @NonNls final String delim = " -> ";
   final StringBuffer buf = new StringBuffer();
   processDependencies(
       getSelectedScope(myLeftTree),
       getSelectedScope(myRightTree),
       new Processor<List<PsiFile>>() {
         public boolean process(final List<PsiFile> path) {
           if (buf.length() > 0) buf.append("<br>");
           buf.append(
               StringUtil.join(
                   path,
                   new Function<PsiFile, String>() {
                     public String fun(final PsiFile psiFile) {
                       return psiFile.getName();
                     }
                   },
                   delim));
           return true;
         }
       });
   final JEditorPane pane =
       new JEditorPane(UIUtil.HTML_MIME, "<html>" + buf.toString() + "</html>");
   pane.setForeground(Color.black);
   pane.setBackground(HintUtil.INFORMATION_COLOR);
   pane.setOpaque(true);
   final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(pane);
   final Dimension dimension = pane.getPreferredSize();
   scrollPane.setMinimumSize(new Dimension(dimension.width, dimension.height + 20));
   scrollPane.setPreferredSize(new Dimension(dimension.width, dimension.height + 20));
   JBPopupFactory.getInstance()
       .createComponentPopupBuilder(scrollPane, pane)
       .setTitle("Dependencies")
       .setMovable(true)
       .createPopup()
       .showInBestPositionFor(e.getDataContext());
 }
  public DependenciesPanel(
      Project project, final List<DependenciesBuilder> builders, final Set<PsiFile> excluded) {
    super(new BorderLayout());
    myBuilders = builders;
    myExcluded = excluded;
    final DependenciesBuilder main = myBuilders.get(0);
    myForward = !main.isBackward();
    myScopeOfInterest = main.getScopeOfInterest();
    myTransitiveBorder = main.getTransitiveBorder();
    myDependencies = new HashMap<PsiFile, Set<PsiFile>>();
    myIllegalDependencies = new HashMap<PsiFile, Map<DependencyRule, Set<PsiFile>>>();
    for (DependenciesBuilder builder : builders) {
      myDependencies.putAll(builder.getDependencies());
      myIllegalDependencies.putAll(builder.getIllegalDependencies());
    }
    exclude(excluded);
    myProject = project;
    myUsagesPanel = new DependenciesUsagesPanel(myProject, myBuilders);
    Disposer.register(this, myUsagesPanel);

    final Splitter treeSplitter = new Splitter();
    Disposer.register(
        this,
        new Disposable() {
          public void dispose() {
            treeSplitter.dispose();
          }
        });
    treeSplitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myLeftTree));
    treeSplitter.setSecondComponent(ScrollPaneFactory.createScrollPane(myRightTree));

    final Splitter splitter = new Splitter(true);
    Disposer.register(
        this,
        new Disposable() {
          public void dispose() {
            splitter.dispose();
          }
        });
    splitter.setFirstComponent(treeSplitter);
    splitter.setSecondComponent(myUsagesPanel);
    add(splitter, BorderLayout.CENTER);
    add(createToolbar(), BorderLayout.NORTH);

    myRightTreeExpansionMonitor = PackageTreeExpansionMonitor.install(myRightTree, myProject);
    myLeftTreeExpansionMonitor = PackageTreeExpansionMonitor.install(myLeftTree, myProject);

    myRightTreeMarker =
        new Marker() {
          public boolean isMarked(VirtualFile file) {
            return myIllegalsInRightTree.contains(file);
          }
        };

    myLeftTreeMarker =
        new Marker() {
          public boolean isMarked(VirtualFile file) {
            return myIllegalDependencies.containsKey(file);
          }
        };

    updateLeftTreeModel();
    updateRightTreeModel();

    myLeftTree
        .getSelectionModel()
        .addTreeSelectionListener(
            new TreeSelectionListener() {
              public void valueChanged(TreeSelectionEvent e) {
                updateRightTreeModel();
                final StringBuffer denyRules = new StringBuffer();
                final StringBuffer allowRules = new StringBuffer();
                final TreePath[] paths = myLeftTree.getSelectionPaths();
                if (paths == null) {
                  return;
                }
                for (TreePath path : paths) {
                  PackageDependenciesNode selectedNode =
                      (PackageDependenciesNode) path.getLastPathComponent();
                  traverseToLeaves(selectedNode, denyRules, allowRules);
                }
                if (denyRules.length() + allowRules.length() > 0) {
                  StatusBar.Info.set(
                      AnalysisScopeBundle.message(
                          "status.bar.rule.violation.message",
                          ((denyRules.length() == 0 || allowRules.length() == 0) ? 1 : 2),
                          (denyRules.length() > 0
                                  ? denyRules.toString() + (allowRules.length() > 0 ? "; " : "")
                                  : " ")
                              + (allowRules.length() > 0 ? allowRules.toString() : " ")),
                      myProject);
                } else {
                  StatusBar.Info.set(
                      AnalysisScopeBundle.message("status.bar.no.rule.violation.message"),
                      myProject);
                }
              }
            });

    myRightTree
        .getSelectionModel()
        .addTreeSelectionListener(
            new TreeSelectionListener() {
              public void valueChanged(TreeSelectionEvent e) {
                SwingUtilities.invokeLater(
                    new Runnable() {
                      public void run() {
                        final Set<PsiFile> searchIn = getSelectedScope(myLeftTree);
                        final Set<PsiFile> searchFor = getSelectedScope(myRightTree);
                        if (searchIn.isEmpty() || searchFor.isEmpty()) {
                          myUsagesPanel.setToInitialPosition();
                          processDependencies(
                              searchIn,
                              searchFor,
                              new Processor<List<PsiFile>>() { // todo do not show too many usages
                                public boolean process(final List<PsiFile> path) {
                                  searchFor.add(path.get(1));
                                  return true;
                                }
                              });
                        } else {
                          myUsagesPanel.findUsages(searchIn, searchFor);
                        }
                      }
                    });
              }
            });

    initTree(myLeftTree, false);
    initTree(myRightTree, true);

    if (builders.size() == 1) {
      AnalysisScope scope = builders.get(0).getScope();
      if (scope.getScopeType() == AnalysisScope.FILE) {
        Set<PsiFile> oneFileSet = myDependencies.keySet();
        if (oneFileSet.size() == 1) {
          selectElementInLeftTree(oneFileSet.iterator().next());
          return;
        }
      }
    }
    TreeUtil.selectFirstNode(myLeftTree);
  }