ProjectView tests up again
[fedora-idea.git] / lang-impl / src / com / intellij / ide / projectView / BaseProjectTreeBuilder.java
blobe2a6761644452174b2547f64bd8d54d4eb822b8e
1 package com.intellij.ide.projectView;
3 import com.intellij.ide.favoritesTreeView.FavoritesTreeNodeDescriptor;
4 import com.intellij.ide.util.treeView.AbstractTreeBuilder;
5 import com.intellij.ide.util.treeView.AbstractTreeNode;
6 import com.intellij.ide.util.treeView.AbstractTreeStructure;
7 import com.intellij.ide.util.treeView.NodeDescriptor;
8 import com.intellij.openapi.progress.ProgressIndicator;
9 import com.intellij.openapi.progress.util.StatusBarProgress;
10 import com.intellij.openapi.project.Project;
11 import com.intellij.openapi.util.ActionCallback;
12 import com.intellij.openapi.util.AsyncResult;
13 import com.intellij.openapi.util.Condition;
14 import com.intellij.openapi.util.Conditions;
15 import com.intellij.openapi.vfs.VirtualFile;
16 import com.intellij.openapi.wm.IdeFocusManager;
17 import com.intellij.psi.PsiDirectory;
18 import com.intellij.psi.PsiFile;
19 import org.jetbrains.annotations.NotNull;
21 import javax.swing.*;
22 import javax.swing.tree.DefaultMutableTreeNode;
23 import javax.swing.tree.DefaultTreeModel;
24 import javax.swing.tree.TreeNode;
25 import javax.swing.tree.TreePath;
26 import java.util.ArrayList;
27 import java.util.Comparator;
28 import java.util.List;
30 public abstract class BaseProjectTreeBuilder extends AbstractTreeBuilder {
31 protected final Project myProject;
33 public BaseProjectTreeBuilder(Project project,
34 JTree tree,
35 DefaultTreeModel treeModel,
36 AbstractTreeStructure treeStructure,
37 Comparator<NodeDescriptor> comparator) {
38 super(tree, treeModel, treeStructure, comparator);
39 myProject = project;
42 protected boolean isAlwaysShowPlus(NodeDescriptor nodeDescriptor) {
43 return ((AbstractTreeNode)nodeDescriptor).isAlwaysShowPlus();
46 protected boolean isAutoExpandNode(NodeDescriptor nodeDescriptor) {
47 return nodeDescriptor.getParentDescriptor() == null;
50 protected final void expandNodeChildren(final DefaultMutableTreeNode node) {
51 Object element = ((NodeDescriptor)node.getUserObject()).getElement();
52 VirtualFile virtualFile = getFileToRefresh(element);
53 super.expandNodeChildren(node);
54 if (virtualFile != null) {
55 virtualFile.refresh(true, false);
59 private static VirtualFile getFileToRefresh(Object element) {
60 return element instanceof PsiDirectory
61 ? ((PsiDirectory)element).getVirtualFile()
62 : element instanceof PsiFile ? ((PsiFile)element).getVirtualFile() : null;
65 private List<AbstractTreeNode> getOrBuildChildren(AbstractTreeNode parent) {
66 buildNodeForElement(parent);
68 DefaultMutableTreeNode node = getNodeForElement(parent);
70 if (node == null) {
71 return new ArrayList<AbstractTreeNode>();
74 getTree().expandPath(new TreePath(node.getPath()));
76 return collectChildren(node);
79 private List<AbstractTreeNode> collectChildren(DefaultMutableTreeNode node) {
80 int childCount = node.getChildCount();
81 List<AbstractTreeNode> result = new ArrayList<AbstractTreeNode>(childCount);
82 for (int i = 0; i < childCount; i++) {
83 TreeNode childAt = node.getChildAt(i);
84 DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode)childAt;
85 if (defaultMutableTreeNode.getUserObject() instanceof AbstractTreeNode) {
86 ProjectViewNode treeNode = (ProjectViewNode)defaultMutableTreeNode.getUserObject();
87 result.add(treeNode);
89 else if (defaultMutableTreeNode.getUserObject() instanceof FavoritesTreeNodeDescriptor) {
90 AbstractTreeNode treeNode = ((FavoritesTreeNodeDescriptor)defaultMutableTreeNode.getUserObject()).getElement();
91 result.add(treeNode);
94 return result;
97 public ActionCallback select(Object element, VirtualFile file, final boolean requestFocus) {
98 return _select(element, file, requestFocus, Conditions.<AbstractTreeNode>alwaysTrue());
101 public ActionCallback selectInWidth(final Object element,
102 final boolean requestFocus,
103 final Condition<AbstractTreeNode> nonStopCondition) {
104 return _select(element, null, requestFocus, nonStopCondition);
107 private ActionCallback _select(Object element,
108 VirtualFile file,
109 final boolean requestFocus,
110 final Condition<AbstractTreeNode> nonStopCondition) {
111 final ActionCallback result = new ActionCallback();
113 DefaultMutableTreeNode selected = alreadySelectedNode(element);
115 final Runnable onDone = new Runnable() {
116 public void run() {
117 if (requestFocus) {
118 IdeFocusManager.getInstance(myProject).requestFocus(getTree(), true);
121 result.setDone();
125 final Condition<AbstractTreeNode> condition = new Condition<AbstractTreeNode>() {
126 public boolean value(AbstractTreeNode abstractTreeNode) {
127 if (result.isProcessed()) return false;
128 return nonStopCondition.value(abstractTreeNode);
132 if (selected == null) {
133 expandPathTo(file, (AbstractTreeNode)getTreeStructure().getRootElement(), element, condition)
134 .doWhenDone(new AsyncResult.Handler<AbstractTreeNode>() {
135 public void run(AbstractTreeNode node) {
136 select(node, onDone);
138 }).notifyWhenRejected(result);
140 else {
141 onDone.run();
144 return result;
147 // returns selected node for element or null if element node is not selected
148 private DefaultMutableTreeNode alreadySelectedNode(final Object element) {
149 final TreePath[] selectionPaths = getTree().getSelectionPaths();
150 if (selectionPaths == null || selectionPaths.length == 0) {
151 return null;
153 for (TreePath selectionPath : selectionPaths) {
154 Object selected = selectionPath.getLastPathComponent();
155 if (elementIsEqualTo(selected, element)) {
156 return (DefaultMutableTreeNode)selected;
159 return null;
162 private static boolean elementIsEqualTo(final Object node, final Object element) {
163 if (node instanceof DefaultMutableTreeNode) {
164 final Object userObject = ((DefaultMutableTreeNode)node).getUserObject();
165 if (userObject instanceof ProjectViewNode) {
166 final AbstractTreeNode projectViewNode = (ProjectViewNode)userObject;
167 return projectViewNode.canRepresent(element);
170 return false;
173 private AsyncResult<AbstractTreeNode> expandPathTo(final VirtualFile file,
174 final AbstractTreeNode root,
175 final Object element,
176 final Condition<AbstractTreeNode> nonStopCondition) {
177 final AsyncResult<AbstractTreeNode> async = new AsyncResult<AbstractTreeNode>();
179 if (root.canRepresent(element)) {
180 expand(root, new Runnable() {
181 public void run() {
182 async.setDone(root);
185 return async;
188 if (root instanceof ProjectViewNode && file != null && !((ProjectViewNode)root).contains(file)) {
189 async.setRejected();
190 return async;
194 expand(root, new Runnable() {
195 public void run() {
196 final DefaultMutableTreeNode rootNode = getNodeForElement(root);
197 if (rootNode != null) {
198 final List<AbstractTreeNode> kids = collectChildren(rootNode);
199 expandChild(kids, 0, nonStopCondition, file, element, async);
201 else {
202 async.setRejected();
207 return async;
210 private void expandChild(final List<AbstractTreeNode> kids, final int i, final Condition<AbstractTreeNode> nonStopCondition, final VirtualFile file,
211 final Object element,
212 final AsyncResult<AbstractTreeNode> async) {
214 if (i >= kids.size()) {
215 async.setRejected();
216 return;
219 final AbstractTreeNode eachKid = kids.get(i);
220 final boolean[] nodeWasCollapsed = new boolean[] {true};
221 final DefaultMutableTreeNode nodeForElement = getNodeForElement(eachKid);
222 if (nodeForElement != null) {
223 nodeWasCollapsed[0] = getTree().isCollapsed(new TreePath(nodeForElement.getPath()));
226 if (nonStopCondition.value(eachKid)) {
227 expandPathTo(file, eachKid, element, nonStopCondition).doWhenDone(new AsyncResult.Handler<AbstractTreeNode>() {
228 public void run(AbstractTreeNode abstractTreeNode) {
229 async.setDone(abstractTreeNode);
231 }).doWhenRejected(new Runnable() {
232 public void run() {
233 if (nodeWasCollapsed[0]) {
234 collapseChildren(eachKid, null);
236 expandChild(kids, i + 1, nonStopCondition, file, element, async);
239 } else {
240 async.setRejected();
244 protected boolean validateNode(final Object child) {
245 if (child instanceof ProjectViewNode) {
246 final ProjectViewNode projectViewNode = (ProjectViewNode)child;
247 return projectViewNode.validate();
249 return true;
252 @NotNull
253 protected ProgressIndicator createProgressIndicator() {
254 return new StatusBarProgress();