TreeUi: bg loading tested and fixed
[fedora-idea.git] / platform-api / src / com / intellij / ide / util / treeView / UpdaterTreeState.java
blobb8aa9bf9111c29d60cc9cd66ae68a13c950bcecd
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;
8 import javax.swing.*;
9 import javax.swing.tree.DefaultMutableTreeNode;
10 import javax.swing.tree.TreePath;
11 import java.util.*;
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) {
25 myUi = 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) {
34 target.put(o, o);
38 private Set<Object> addPaths(Object[] elements) {
39 Set<Object> set = new HashSet<Object>();
40 if (elements != null) {
41 set.addAll(Arrays.asList(elements));
44 return addPaths(set);
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) {
70 target.add(element);
76 return target;
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;
89 try {
90 myProcessingNow = true;
91 runnable.run();
93 finally {
94 if (!oldValue) {
95 myProcessingNow = false;
99 return isEmpty();
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);
137 clearSelection();
138 clearExpansion();
140 myUi._select(toSelect, new Runnable() {
141 public void run() {
142 processUnsuccessfulSelections(toSelect, new Function<Object, Object>() {
143 public Object fun(final Object o) {
144 addSelection(o);
145 return o;
149 processAjusted(adjusted).doWhenDone(new Runnable() {
150 public void run() {
151 myUi.expand(toExpand, new Runnable() {
152 public void run() {
153 if (!isEmpty()) {
154 myCanRunRestore = false;
155 myUi.setUpdaterState(UpdaterTreeState.this);
157 myProcessingNow = false;
159 }, true);
163 }, false, true, true);
165 return 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;
192 toSelect.add(each);
194 if (allSelected.size() == 0) {
195 toSelect.add(each);
199 final Object[] newSelection = ArrayUtil.toObjectArray(toSelect);
201 myUi._select(newSelection, new Runnable() {
202 public void run() {
203 processUnsuccessfulSelections(newSelection, new Function<Object, Object>() {
204 public Object fun(final Object o) {
205 addAdjustedSelection(o, adjusted.get(o));
206 return null;
209 result.setDone();
211 }, true, true, true);
213 return result;
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);
223 return false;
226 public void clearExpansion() {
227 myToExpand.clear();
230 public void clearSelection() {
231 myToSelect.clear();
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);