Package org.twodividedbyzero.idea.findbugs.gui.tree

Source Code of org.twodividedbyzero.idea.findbugs.gui.tree.BugTreeHelper

/*
* Copyright 2008-2013 Andre Pfeiler
*
* This file is part of FindBugs-IDEA.
*
* FindBugs-IDEA is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FindBugs-IDEA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FindBugs-IDEA.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.twodividedbyzero.idea.findbugs.gui.tree;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import edu.umd.cs.findbugs.BugInstance;
import org.jetbrains.annotations.Nullable;
import org.twodividedbyzero.idea.findbugs.common.EventDispatchThreadHelper;
import org.twodividedbyzero.idea.findbugs.common.util.IdeaUtilImpl;
import org.twodividedbyzero.idea.findbugs.gui.tree.model.AbstractTreeNode;
import org.twodividedbyzero.idea.findbugs.gui.tree.model.BugInstanceGroupNode;
import org.twodividedbyzero.idea.findbugs.gui.tree.model.BugInstanceNode;
import org.twodividedbyzero.idea.findbugs.gui.tree.model.GroupTreeModel;
import org.twodividedbyzero.idea.findbugs.gui.tree.model.VisitableTreeNode;

import javax.swing.JTree;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


/**
* $Date: 2014-06-19 18:40:49 -0500 (Thu, 19 Jun 2014) $
*
* @author Andre Pfeiler<andrepdo@dev.java.net>
* @version $Revision: 314 $
* @since 0.9.8-dev
*/
public class BugTreeHelper {

  private static final Logger LOGGER = Logger.getInstance(BugTreeHelper.class.getName());

  private final JTree _tree;
  private final Project _project;


  private BugTreeHelper(final JTree tree, final Project project) {
    _tree = tree;
    _project = project;
  }


  public static BugTreeHelper create(final JTree tree, final Project project) {
    return new BugTreeHelper(tree, project);
  }


  @Nullable
  public PsiElement getSelectedElement() {
    final TreePath treepath = _tree.getSelectionPath();
    if (treepath == null) {
      return null;
    }

    @SuppressWarnings({"unchecked"})
    final AbstractTreeNode<VisitableTreeNode> treeNode = (AbstractTreeNode<VisitableTreeNode>) treepath.getLastPathComponent();
    PsiElement psiElement = null;

    if (treeNode == null) {
      return null;
    }
    if (treeNode instanceof BugInstanceNode) {
      final BugInstanceNode node = (BugInstanceNode) treeNode;
      if (node.getPsiFile() != null) {
        return node.getPsiFile();
      } else {
        final PsiClass psiClass = IdeaUtilImpl.findJavaPsiClass(_project, node.getSourcePath());
        LOGGER.debug("BugTreeHelper#getSeletedElement(" + _project + ", " + node.getSourcePath() + ')');
        if (psiClass != null) {
          LOGGER.debug("Found: psiClass (" + psiClass.getName() + ')');
          psiElement = IdeaUtilImpl.getPsiFile(psiClass);
          if (psiElement != null) {
            LOGGER.debug("BugTreeHelper - IdeaUtilImpl.getPsiFile(psiClass) - found - psiElement: [" + psiElement.getText() + ']');
            node.setPsiFile((PsiFile) psiElement);
          } else {
            LOGGER.debug("BugTreeHelper - IdeaUtilImpl.getPsiFile(psiClass) - found - psiClass: [" + psiClass + ']');
          }
        }
      }
    }

    if (psiElement != null) {
      return psiElement;
    } else {
      return getSelectedFile();
    }
  }


  @Nullable
  public PsiFile getSelectedFile() {
    final TreePath treepath = _tree.getSelectionPath();
    if (treepath == null) {
      return null;
    }

    @SuppressWarnings({"unchecked"})
    final AbstractTreeNode<VisitableTreeNode> treeNode = (AbstractTreeNode<VisitableTreeNode>) treepath.getLastPathComponent();

    if (treeNode == null) {
      return null;
    } else {
      if (treeNode instanceof BugInstanceNode) {
        final BugInstanceNode node = (BugInstanceNode) treeNode;
        if (node.getPsiFile() != null) {
          return node.getPsiFile();
        } else {
          final PsiClass psiClass = IdeaUtilImpl.findJavaPsiClass(_project, node.getSourcePath());
          LOGGER.debug("BugTreeHelper#getSelectedFile(" + _project + ", " + node.getSourcePath() + ')');
          if (psiClass != null) {
            LOGGER.debug("Found: psiClass (" + psiClass.getName() + ')');
            final PsiFile psiFile = IdeaUtilImpl.getPsiFile(psiClass);
            if (psiFile != null) {
              LOGGER.debug("BugTreeHelper - IdeaUtilImpl.getPsiFile(psiClass) - found - psiFile: " + psiFile.getName());
              node.setPsiFile(psiFile);
            } else {
              LOGGER.debug("BugTreeHelper - IdeaUtilImpl.getPsiFile(psiClass) - NOT found - psiClass: " + psiClass);
            }
            return psiFile;
          } else {
            return null;
          }
        }
      }
      return null;
    }
  }


  @Nullable
  public BugInstanceNode selectPreviousNode() {
    final TreePath treepath = _tree.getSelectionPath();
    if (treepath == null) {
      return null;
    }


    @SuppressWarnings({"unchecked"})
    final AbstractTreeNode<VisitableTreeNode> treeNode = (AbstractTreeNode<VisitableTreeNode>) treepath.getLastPathComponent();


    final BugInstanceNode bugInstanceNode = getPreviousBugInstanceLeafNode(treeNode);

    if (bugInstanceNode != null) {
      final TreePath path = getPath(bugInstanceNode);
      _tree.expandPath(path);
      _tree.setExpandsSelectedPaths(true);
      _tree.setSelectionPath(path);
      scrollPathToVisible(path);
    }

    return bugInstanceNode;
  }


  @Nullable
  public BugInstanceNode selectNextNode() {
    final TreePath treepath = _tree.getSelectionPath();
    if (treepath == null) {
      return null;
    }

    final TreePath path = _tree.getPathForRow(_tree.getRowForPath(treepath) + 1);

    //noinspection unchecked
    final AbstractTreeNode<VisitableTreeNode> lastPathComponent = (AbstractTreeNode<VisitableTreeNode>) path.getLastPathComponent();
    final BugInstanceNode nextBugInstanceLeafNode = getNextBugInstanceLeafNode(lastPathComponent);
    if (nextBugInstanceLeafNode == null) {
      return null;
    }
    final TreePath treePath = getPath(nextBugInstanceLeafNode);


    _tree.setExpandsSelectedPaths(true);
    _tree.expandPath(treePath);
    _tree.setSelectionPath(treePath);
    scrollPathToVisible(treePath);

    return nextBugInstanceLeafNode;
  }


  @Nullable
  private static BugInstanceNode getNextBugInstanceLeafNode(final AbstractTreeNode<VisitableTreeNode> node) {
    if (node instanceof BugInstanceNode) {
      return (BugInstanceNode) node;
    }
    final List<VisitableTreeNode> childList = node.getChildsList();
    for (final VisitableTreeNode childNode : childList) {
      //noinspection unchecked
      final BugInstanceNode result = childNode instanceof BugInstanceNode ? (BugInstanceNode) childNode : getNextBugInstanceLeafNode((AbstractTreeNode<VisitableTreeNode>) childNode);
      if (result != null) {
        return result;
      }
    }
    return null;
  }


  // todo: fix me
  @edu.umd.cs.findbugs.annotations.SuppressFBWarnings({"BC_UNCONFIRMED_CAST_OF_RETURN_VALUE"})
  @Nullable
  private BugInstanceNode getPreviousBugInstanceLeafNode(@SuppressWarnings("TypeMayBeWeakened") final AbstractTreeNode<VisitableTreeNode> node) {
    if (node instanceof BugInstanceNode) {
      return (BugInstanceNode) node;
    }
    if (_tree.getModel().getRoot().equals(node)) {
      return null;
    }

    @SuppressWarnings("unchecked")
    final List<VisitableTreeNode> childList = (List<VisitableTreeNode>) node.getParent().getChildsList();
    Collections.reverse(childList);
    for (final VisitableTreeNode childNode : childList) {
      //noinspection ObjectEquality
      if (childNode instanceof BugInstanceNode && childNode != node) {
        return  (BugInstanceNode) childNode;
      } else if (childNode instanceof BugInstanceGroupNode) {
        //noinspection TailRecursion,unchecked
        return getPreviousBugInstanceLeafNode((AbstractTreeNode<VisitableTreeNode>) childNode);
      }
    }

    return null;
  }


  public void scrollPathToVisible(final TreePath path) {
    EventDispatchThreadHelper.invokeLater(new Runnable() {
      public void run() {
        _tree.scrollPathToVisible(path);
        _tree.setSelectionPath(path);
      }
    });
  }


  /**
   * Expand the given tree to the given level, starting from the given node
   * and path.
   *
   * @param node  The node to start from
   * @param path  The path to start from
   * @param level The number of levels to expand to
   */
  public void expandNode(final TreeNode node, final TreePath path, final int level) {
    if (level <= 0) {
      return;
    }

    _tree.expandPath(path);

    for (int i = 0; i < node.getChildCount(); ++i) {
      final TreeNode childNode = node.getChildAt(i);
      expandNode(childNode, path.pathByAddingChild(childNode), level - 1);
    }
  }


  /**
   * Expand the error tree to the given level.
   *
   * @param level The level to expand to
   */
  public void expandTree(final int level) {
    expandNode((TreeNode) _tree.getModel().getRoot(), new TreePath(_tree.getModel().getRoot()), level);
  }


  /** Collapse the tree so that only the root node is visible. */
  public void collapseTree() {
    for (int i = 1; i < _tree.getRowCount(); ++i) {
      _tree.collapseRow(i);
    }
  }


  public static TreePath getPath(@Nullable TreeNode node) {
    final List<TreeNode> list = new ArrayList<TreeNode>();

    while (node != null) {
      list.add(node);
      //noinspection AssignmentToMethodParameter
      node = node.getParent();
    }
    Collections.reverse(list);

    return new TreePath(list.toArray());
  }


  // todo:
  private void _buildElementsCache(final Object node, final TreePath path, final TreeModel model) {
    /*if (_tree.isRootVisible() || path.getLastPathComponent() != _tree.getModel().getRoot()) {
      //_elementsCache.add(path);
    }*/
    for (int i = 0; i < model.getChildCount(node); i++) {
      final Object childNode = model.getChild(node, i);
      _buildElementsCache(childNode, path.pathByAddingChild(childNode), model);
    }
  }


  public void gotoNode(final BugInstanceNode node) {
    gotoNode(node.getBugInstance());
  }


  public void gotoNode(final BugInstance bugInstance) {
    final AbstractTreeNode<VisitableTreeNode> node = findTreeNodeByBugInstance(bugInstance);
    final TreePath path = getPath(node);
    scrollPathToVisible(path);
  }


  @Nullable
  private AbstractTreeNode<VisitableTreeNode> findTreeNodeByBugInstance(final BugInstance bugInstance) {
    return ((GroupTreeModel) _tree.getModel()).findNodeByBugInstance(bugInstance);
  }

}
TOP

Related Classes of org.twodividedbyzero.idea.findbugs.gui.tree.BugTreeHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.