1 package com
.intellij
.ide
.util
.treeView
;
3 import com
.intellij
.openapi
.util
.ActionCallback
;
4 import com
.intellij
.openapi
.util
.Condition
;
5 import com
.intellij
.util
.Function
;
6 import com
.intellij
.util
.ArrayUtil
;
9 import javax
.swing
.tree
.DefaultMutableTreeNode
;
10 import javax
.swing
.tree
.TreePath
;
13 public class UpdaterTreeState
{
15 private final AbstractTreeUi myUi
;
16 protected WeakHashMap
<Object
, Object
> myToSelect
= new WeakHashMap
<Object
, Object
>();
17 protected WeakHashMap
<Object
, Condition
> myAdjustedSelection
= new WeakHashMap
<Object
, Condition
>();
18 protected WeakHashMap
<Object
, Object
> myDisposedElements
= new WeakHashMap
<Object
, Object
>();
19 protected WeakHashMap
<Object
, Object
> myToExpand
= new WeakHashMap
<Object
, Object
>();
20 private boolean myProcessingNow
;
22 private boolean myCanRunRestore
= true;
24 public UpdaterTreeState(AbstractTreeUi ui
) {
27 final JTree tree
= myUi
.getTree();
28 putAll(addPaths(tree
.getSelectionPaths()), myToSelect
);
29 putAll(addPaths(tree
.getExpandedDescendants(new TreePath(tree
.getModel().getRoot()))), myToExpand
);
32 private static void putAll(final Set
<Object
> source
, final Map
<Object
, Object
> target
) {
33 for (Object o
: source
) {
38 private Set
<Object
> addPaths(Object
[] elements
) {
39 Set
<Object
> set
= new HashSet
<Object
>();
40 if (elements
!= null) {
41 set
.addAll(Arrays
.asList(elements
));
47 private Set
<Object
> addPaths(Enumeration elements
) {
48 ArrayList
<Object
> elementArray
= new ArrayList
<Object
>();
49 if (elements
!= null) {
50 while (elements
.hasMoreElements()) {
51 Object each
= elements
.nextElement();
52 elementArray
.add(each
);
56 return addPaths(elementArray
);
59 private Set
<Object
> addPaths(Collection elements
) {
60 Set
<Object
> target
= new HashSet
<Object
>();
62 if (elements
!= null) {
63 for (Object each
: elements
) {
64 final Object node
= ((TreePath
)each
).getLastPathComponent();
65 if (node
instanceof DefaultMutableTreeNode
) {
66 final Object descriptor
= ((DefaultMutableTreeNode
)node
).getUserObject();
67 if (descriptor
instanceof NodeDescriptor
) {
68 final Object element
= myUi
.getElementFromDescriptor((NodeDescriptor
)descriptor
);
69 if (element
!= null) {
79 public Object
[] getToSelect() {
80 return myToSelect
.keySet().toArray(new Object
[myToSelect
.size()]);
83 public Object
[] getToExpand() {
84 return myToExpand
.keySet().toArray(new Object
[myToExpand
.size()]);
87 public boolean process(Runnable runnable
) {
88 boolean oldValue
= myProcessingNow
;
90 myProcessingNow
= true;
95 myProcessingNow
= false;
102 public boolean isEmpty() {
103 return myToExpand
.isEmpty() && myToSelect
.isEmpty() && myAdjustedSelection
.isEmpty();
107 public boolean isProcessingNow() {
108 return myProcessingNow
;
111 public void addAll(final UpdaterTreeState state
) {
112 myToExpand
.putAll(state
.myToExpand
);
114 final Iterator
<Object
> toSelect
= state
.myToSelect
.keySet().iterator();
115 while (toSelect
.hasNext()) {
116 Object each
= toSelect
.next();
117 if (!myAdjustedSelection
.containsKey(each
)) {
118 myToSelect
.put(each
, each
);
122 myCanRunRestore
= state
.myCanRunRestore
;
125 public boolean restore() {
126 if (isProcessingNow() || !myCanRunRestore
) return false;
128 myProcessingNow
= true;
130 final Object
[] toSelect
= getToSelect();
131 final Object
[] toExpand
= getToExpand();
134 final Map
<Object
, Condition
> adjusted
= new WeakHashMap
<Object
, Condition
>();
135 adjusted
.putAll(myAdjustedSelection
);
140 myUi
._select(toSelect
, new Runnable() {
142 processUnsuccessfulSelections(toSelect
, new Function
<Object
, Object
>() {
143 public Object
fun(final Object o
) {
149 processAjusted(adjusted
).doWhenDone(new Runnable() {
151 myUi
.expand(toExpand
, new Runnable() {
154 myCanRunRestore
= false;
155 myUi
.setUpdaterState(UpdaterTreeState
.this);
157 myProcessingNow
= false;
163 }, false, true, true);
168 void beforeSubtreeUpdate() {
169 myCanRunRestore
= true;
172 private void processUnsuccessfulSelections(final Object
[] toSelect
, Function
<Object
, Object
> restore
) {
173 final Set
<Object
> selected
= myUi
.getSelectedElements();
174 for (Object eachToSelect
: toSelect
) {
175 if (!selected
.contains(eachToSelect
)) {
176 restore
.fun(eachToSelect
);
181 private ActionCallback
processAjusted(final Map
<Object
, Condition
> adjusted
) {
182 final ActionCallback result
= new ActionCallback();
184 final Set
<Object
> allSelected
= myUi
.getSelectedElements();
186 Set
<Object
> toSelect
= new HashSet
<Object
>();
187 for (Object each
: adjusted
.keySet()) {
188 if (adjusted
.get(each
).value(each
)) continue;
190 for (final Object eachSelected
: allSelected
) {
191 if (isParentOrSame(each
, eachSelected
)) continue;
194 if (allSelected
.size() == 0) {
199 final Object
[] newSelection
= ArrayUtil
.toObjectArray(toSelect
);
201 myUi
._select(newSelection
, new Runnable() {
203 processUnsuccessfulSelections(newSelection
, new Function
<Object
, Object
>() {
204 public Object
fun(final Object o
) {
205 addAdjustedSelection(o
, adjusted
.get(o
));
211 }, true, true, true);
216 private boolean isParentOrSame(Object parent
, Object child
) {
217 Object eachParent
= child
;
218 while (eachParent
!= null) {
219 if (parent
.equals(eachParent
)) return true;
220 eachParent
= myUi
.getTreeStructure().getParentElement(eachParent
);
226 public void clearExpansion() {
230 public void clearSelection() {
232 myAdjustedSelection
= new WeakHashMap
<Object
, Condition
>();
235 public void addSelection(final Object element
) {
236 myToSelect
.put(element
, element
);
239 public void addAdjustedSelection(final Object element
, Condition isExpired
) {
240 myAdjustedSelection
.put(element
, isExpired
);