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
;
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
,
35 DefaultTreeModel treeModel
,
36 AbstractTreeStructure treeStructure
,
37 Comparator
<NodeDescriptor
> comparator
) {
38 super(tree
, treeModel
, treeStructure
, comparator
);
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
);
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();
89 else if (defaultMutableTreeNode
.getUserObject() instanceof FavoritesTreeNodeDescriptor
) {
90 AbstractTreeNode treeNode
= ((FavoritesTreeNodeDescriptor
)defaultMutableTreeNode
.getUserObject()).getElement();
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
,
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() {
118 IdeFocusManager
.getInstance(myProject
).requestFocus(getTree(), true);
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
);
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) {
153 for (TreePath selectionPath
: selectionPaths
) {
154 Object selected
= selectionPath
.getLastPathComponent();
155 if (elementIsEqualTo(selected
, element
)) {
156 return (DefaultMutableTreeNode
)selected
;
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
);
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() {
188 if (root
instanceof ProjectViewNode
&& file
!= null && !((ProjectViewNode
)root
).contains(file
)) {
194 expand(root
, new Runnable() {
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
);
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()) {
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() {
233 if (nodeWasCollapsed
[0]) {
234 collapseChildren(eachKid
, null);
236 expandChild(kids
, i
+ 1, nonStopCondition
, file
, element
, async
);
244 protected boolean validateNode(final Object child
) {
245 if (child
instanceof ProjectViewNode
) {
246 final ProjectViewNode projectViewNode
= (ProjectViewNode
)child
;
247 return projectViewNode
.validate();
253 protected ProgressIndicator
createProgressIndicator() {
254 return new StatusBarProgress();