Package com.intellij.usages.impl

Source Code of com.intellij.usages.impl.GroupNode

/*
* Copyright 2000-2007 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.usages.impl;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.Navigatable;
import com.intellij.usages.Usage;
import com.intellij.usages.UsageGroup;
import com.intellij.usages.UsageView;
import com.intellij.usages.UsageViewSettings;
import com.intellij.usages.rules.MergeableUsage;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import java.util.*;

/**
* @author max
*/
public class GroupNode extends Node implements Navigatable, Comparable<GroupNode> {
  private static final NodeComparator COMPARATOR = new NodeComparator();
  private final UsageGroup myGroup;
  private final int myRuleIndex;
  private final Map<UsageGroup, GroupNode> mySubgroupNodes = new THashMap<UsageGroup, GroupNode>();
  private final List<UsageNode> myUsageNodes = new ArrayList<UsageNode>();
  private volatile int myRecursiveUsageCount = 0;

  public GroupNode(UsageGroup group, int ruleIndex, UsageViewTreeModelBuilder treeModel) {
    super(treeModel);
    setUserObject(group);
    myGroup = group;
    myRuleIndex = ruleIndex;
  }

  protected void updateNotify() {
    myGroup.update();
  }

  public String toString() {
    String result = "";
    if (myGroup != null) result += myGroup.getText(null);
    return children == null ? result : result + children.toString();
  }

  public GroupNode addGroup(@NotNull UsageGroup group, int ruleIndex) {
    GroupNode node = mySubgroupNodes.get(group);
    if (node == null) {
      final GroupNode node1 = node = new GroupNode(group, ruleIndex, getBuilder());
      mySubgroupNodes.put(group, node);

      if (!getBuilder().isDetachedMode()) {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            myTreeModel.insertNodeInto(node1, GroupNode.this, getNodeInsertionIndex(node1));
          }
        });
      }
    }
    return node;
  }

  private UsageViewTreeModelBuilder getBuilder() {
    return (UsageViewTreeModelBuilder)myTreeModel;
  }

  public void removeAllChildren() {
    ApplicationManager.getApplication().assertIsDispatchThread();
    super.removeAllChildren();
    mySubgroupNodes.clear();
    myRecursiveUsageCount = 0;
    myUsageNodes.clear();
    myTreeModel.reload(this);
  }

  private UsageNode tryMerge(Usage usage) {
    if (!(usage instanceof MergeableUsage)) return null;
    if (!UsageViewSettings.getInstance().IS_FILTER_DUPLICATED_LINE) return null;
    for (UsageNode node : myUsageNodes) {
      Usage original = node.getUsage();
      if (original instanceof MergeableUsage) {
        if (((MergeableUsage)original).merge((MergeableUsage)usage)) return node;
      }
    }

    return null;
  }

  public boolean removeUsage(UsageNode usage) {
    ApplicationManager.getApplication().assertIsDispatchThread();
    final Collection<GroupNode> groupNodes = mySubgroupNodes.values();
    for(Iterator<GroupNode> iterator = groupNodes.iterator();iterator.hasNext();) {
      final GroupNode groupNode = iterator.next();

      if(groupNode.removeUsage(usage)) {
        doUpdate();

        if (groupNode.getRecursiveUsageCount() == 0) {
          myTreeModel.removeNodeFromParent(groupNode);
          iterator.remove();
        }
        return true;
      }
    }

    if (myUsageNodes.remove(usage)) {
      doUpdate();
      return true;
    }

    return false;
  }

  private void doUpdate() {
    ApplicationManager.getApplication().assertIsDispatchThread();
    --myRecursiveUsageCount;
    myTreeModel.nodeChanged(this);
  }

  public UsageNode addUsage(Usage usage) {
    UsageNode mergedWith = tryMerge(usage);
    if (mergedWith != null) {
      return mergedWith;
    }
    final UsageNode node = new UsageNode(usage, getBuilder());
    myUsageNodes.add(node);
    if (!getBuilder().isDetachedMode()) {
      SwingUtilities.invokeLater(new Runnable() {
        public void run() {
          myTreeModel.insertNodeInto(node, GroupNode.this, getNodeIndex(node));
          incrementUsageCount();
        }
      });
    }
    return node;
  }

  private int getNodeIndex(final UsageNode node) {
    int index = indexedBinarySearch(node);
    return index >= 0 ? index : -index-1;
  }

  private int indexedBinarySearch(UsageNode key) {
    int low = 0;
    int high = getChildCount() - 1;

    while (low <= high) {
      int mid = (low + high) / 2;
      TreeNode treeNode = getChildAt(mid);
      int cmp;
      if (treeNode instanceof UsageNode) {
        UsageNode midVal = (UsageNode)treeNode;
        cmp = midVal.compareTo(key);
      }
      else {
        cmp = -1;
      }
      if (cmp < 0) {
        low = mid + 1;
      }
      else if (cmp > 0) {
        high = mid - 1;
      }
      else {
        return mid; // key found
      }
    }
    return -(low + 1)// key not found
  }


  private void incrementUsageCount() {
    GroupNode groupNode = this;
    while (true) {
      groupNode.myRecursiveUsageCount++;
      final GroupNode node = groupNode;
      myTreeModel.nodeChanged(node);
      TreeNode parent = groupNode.getParent();
      if (!(parent instanceof GroupNode)) return;
      groupNode = (GroupNode)parent;
    }
  }

  public String tree2string(int indent, String lineSeparator) {
    StringBuffer result = new StringBuffer();
    StringUtil.repeatSymbol(result, ' ', indent);

    if (myGroup != null) result.append(myGroup.toString());
    result.append("[");
    result.append(lineSeparator);

    Enumeration enumeration = children();
    while (enumeration.hasMoreElements()) {
      Node node = (Node)enumeration.nextElement();
      result.append(node.tree2string(indent + 4, lineSeparator));
      result.append(lineSeparator);
    }

    StringUtil.repeatSymbol(result, ' ', indent);
    result.append("]");
    result.append(lineSeparator);

    return result.toString();
  }

  protected boolean isDataValid() {
    return myGroup == null || myGroup.isValid();
  }

  protected boolean isDataReadOnly() {
    Enumeration enumeration = children();
    while (enumeration.hasMoreElements()) {
      Node node = (Node)enumeration.nextElement();
      if (node.isReadOnly()) return true;
    }
    return false;
  }

  int getNodeInsertionIndex(DefaultMutableTreeNode node) {
    Enumeration children = children();
    int idx = 0;
    while (children.hasMoreElements()) {
      DefaultMutableTreeNode child = (DefaultMutableTreeNode)children.nextElement();
      if (COMPARATOR.compare(child, node) >= 0) break;
      idx++;
    }
    return idx;
  }

  private static class NodeComparator implements Comparator<DefaultMutableTreeNode> {
    private static int getClassIndex(DefaultMutableTreeNode node) {
      if (node instanceof UsageNode) return 3;
      if (node instanceof GroupNode) return 2;
      if (node instanceof UsageTargetNode) return 1;
      return 0;
    }

    public int compare(DefaultMutableTreeNode n1, DefaultMutableTreeNode n2) {
      int classIdx1 = getClassIndex(n1);
      int classIdx2 = getClassIndex(n2);
      if (classIdx1 != classIdx2) return classIdx1 - classIdx2;
      if (classIdx1 == 2) return ((GroupNode)n1).compareTo((GroupNode)n2);

      return 0;
    }
  }

  public int compareTo(GroupNode groupNode) {
    if (myRuleIndex == groupNode.myRuleIndex) {
      return myGroup.compareTo(groupNode.myGroup);
    }

    return myRuleIndex - groupNode.myRuleIndex;
  }

  public UsageGroup getGroup() {
    return myGroup;
  }

  public int getRecursiveUsageCount() {
    return myRecursiveUsageCount;
  }

  public void navigate(boolean requestFocus) {
    if (myGroup != null) {
      myGroup.navigate(requestFocus);
    }
  }

  public boolean canNavigate() {
    return myGroup != null && myGroup.canNavigate();
  }

  public boolean canNavigateToSource() {
    return myGroup != null && myGroup.canNavigateToSource();
  }


  protected boolean isDataExcluded() {
    Enumeration enumeration = children();
    while (enumeration.hasMoreElements()) {
      Node node = (Node)enumeration.nextElement();
      if (!node.isExcluded()) return false;
    }
    return true;
  }

  protected String getText(UsageView view) {
    return myGroup.getText(view);
  }

  public Collection<GroupNode> getSubGroups() {
    return mySubgroupNodes.values();
  }
  public Collection<UsageNode> getUsageNodes() {
    return myUsageNodes;
  }
}
TOP

Related Classes of com.intellij.usages.impl.GroupNode

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.