1 12 package org.eclipse.jface.internal.databinding.provisional.viewers; 13 14 import java.util.ArrayList ; 15 import java.util.Collections ; 16 import java.util.HashMap ; 17 import java.util.HashSet ; 18 import java.util.Iterator ; 19 import java.util.LinkedList ; 20 import java.util.List ; 21 import java.util.Set ; 22 23 import org.eclipse.core.databinding.observable.Diffs; 24 import org.eclipse.core.databinding.observable.set.AbstractObservableSet; 25 import org.eclipse.core.databinding.observable.set.IObservableSet; 26 import org.eclipse.core.databinding.observable.set.SetDiff; 27 import org.eclipse.core.internal.databinding.observable.tree.IUnorderedTreeProvider; 28 import org.eclipse.jface.viewers.ITreeContentProvider; 29 import org.eclipse.jface.viewers.ITreePathContentProvider; 30 import org.eclipse.jface.viewers.ITreeViewerListener; 31 import org.eclipse.jface.viewers.TreeExpansionEvent; 32 import org.eclipse.jface.viewers.TreePath; 33 import org.eclipse.jface.viewers.TreeViewer; 34 import org.eclipse.jface.viewers.Viewer; 35 36 41 public class UnorderedTreeContentProvider implements ITreeContentProvider, ITreePathContentProvider { 42 43 private HashMap mapElementToTreeNode = new HashMap (); 44 private LinkedList enqueuedPrefetches = new LinkedList (); 45 private IParentProvider rootParentProvider = null; 46 private boolean useTreePaths = false; 47 48 class KnownElementsSet extends AbstractObservableSet { 49 50 protected KnownElementsSet() { 51 super(); 52 } 53 54 57 protected Set getWrappedSet() { 58 return mapElementToTreeNode.keySet(); 59 } 60 61 void doFireDiff(Set added, Set removed) { 62 fireSetChange(Diffs.createSetDiff(added, removed)); 63 } 64 65 public void fireSetChange(SetDiff diff) { 66 super.fireSetChange(diff); 67 } 68 69 void doFireStale(boolean isStale) { 70 if (isStale) { 71 fireStale(); 72 } else { 73 fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, Collections.EMPTY_SET)); 74 } 75 } 76 77 80 public Object getElementType() { 81 return new Object (); 82 } 83 } 84 85 KnownElementsSet elements = new KnownElementsSet(); 86 87 private ITreeViewerListener expandListener = new ITreeViewerListener() { 88 public void treeCollapsed(TreeExpansionEvent event) { 89 } 90 91 public void treeExpanded(TreeExpansionEvent event) { 92 } 93 }; 94 95 private IUnorderedTreeProvider provider; 96 private Object pendingNode; 97 98 private int avoidViewerUpdates; 99 100 private TreeViewer treeViewer; 101 102 private int staleCount = 0; 103 private boolean useRefresh; 104 private int maxPrefetches = 0; 105 106 115 public UnorderedTreeContentProvider(IUnorderedTreeProvider provider, 116 Object pendingNode, boolean useRefresh) { 117 this.provider = provider; 118 this.pendingNode = pendingNode; 119 this.useRefresh = useRefresh; 120 } 121 122 149 public void useTreePaths(boolean usePaths) { 150 this.useTreePaths = usePaths; 151 } 152 153 156 public void setRootPath(IParentProvider rootParentProvider) { 157 this.rootParentProvider = rootParentProvider; 158 } 159 160 163 public void setMaxPrefetches(int maxPrefetches) { 164 this.maxPrefetches = maxPrefetches; 165 } 166 167 IObservableSet createChildSet(Object element) { 168 return provider.createChildSet(element); 169 } 170 171 void remove(Object element, Set removals, boolean lastElement) { 172 if (removals.isEmpty()) { 173 return; 174 } 175 if (avoidViewerUpdates == 0) { 176 if (lastElement || useRefresh) { 177 doRefresh(element); 178 } else { 179 if (useTreePaths) { 180 List toRemove = new ArrayList (); 181 TreePath[] parents = getParents(element); 182 for (int i = 0; i < parents.length; i++) { 183 TreePath parent = parents[i]; 184 185 for (Iterator iter = removals.iterator(); iter.hasNext();) { 186 Object elementToRemove = (Object ) iter.next(); 187 188 toRemove.add(parent.createChildPath(element).createChildPath(elementToRemove)); 189 } 190 } 191 192 treeViewer.remove((TreePath[]) toRemove.toArray(new TreePath[toRemove.size()])); 193 } else { 194 treeViewer.remove(element, removals.toArray()); 195 } 196 } 197 for (Iterator iter = removals.iterator(); iter.hasNext();) { 198 Object next = (Object ) iter.next(); 199 200 TreeNode nextNode = (TreeNode)mapElementToTreeNode.get(next); 201 if (nextNode != null) { 202 nextNode.removeParent(element); 203 removeIfUnused(nextNode); 204 } 205 } 206 } 207 } 208 209 void add(Object element, Set additions) { 210 if (additions.isEmpty()) { 211 return; 212 } 213 if (avoidViewerUpdates == 0) { 214 addParent(element, additions); 216 if (useRefresh) { 217 doRefresh(element); 218 } else { 219 if (useTreePaths) { 220 TreePath[] parents = getParents(element); 221 for (int i = 0; i < parents.length; i++) { 222 TreePath parent = parents[i]; 223 224 treeViewer.add(parent.createChildPath(element), additions.toArray()); 225 } 226 } else { 227 treeViewer.add(element, additions.toArray()); 228 } 229 } 230 } 231 } 232 233 private void doRefresh(Object element) { 234 treeViewer.refresh(element); 235 } 236 237 244 private void addParent(Object parent, Set children) { 245 for (Iterator iter = children.iterator(); iter.hasNext();) { 246 Object next = (Object ) iter.next(); 247 248 TreeNode nextNode = getNode(next); 249 nextNode.addParent(parent); 250 } 251 } 252 253 256 public final Object getPendingNode() { 257 return pendingNode; 258 } 259 260 264 public IObservableSet getChildrenSet(Object parent) { 265 IObservableSet result = getNode(parent).getChildrenSet(); 266 267 return result; 268 } 269 270 public void dispose() { 271 if (treeViewer != null) { 272 try { 273 avoidViewerUpdates++; 274 enqueuedPrefetches.clear(); 275 Object [] keys = mapElementToTreeNode.keySet().toArray(); 276 277 for (int i = 0; i < keys.length; i++) { 278 Object key = keys[i]; 279 280 TreeNode result = (TreeNode)mapElementToTreeNode.get(key); 281 if (result != null) { 282 result.dispose(); 283 } 284 } 285 setViewer(null); 286 } finally { 287 avoidViewerUpdates--; 288 } 289 } 290 } 291 292 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { 293 setViewer(viewer); 295 296 if (oldInput != null && newInput != null && oldInput.equals(newInput)) { 297 return; 298 } 299 300 try { 301 avoidViewerUpdates++; 302 TreeNode oldNode = (TreeNode)mapElementToTreeNode.get(oldInput); 303 if (oldNode != null) { 304 removeIfUnused(oldNode); 305 } 306 } finally { 307 avoidViewerUpdates--; 308 } 309 } 310 311 private void removeIfUnused(TreeNode toRemove) { 312 Object element = toRemove.getElement(); 314 if (toRemove.getParent() == null) { 315 mapElementToTreeNode.remove(element); 316 elements.doFireDiff(Collections.EMPTY_SET, Collections.singleton(element)); 317 toRemove.dispose(); 318 } 319 } 320 321 private void setViewer(Viewer viewer) { 322 if (viewer != null && !(viewer instanceof TreeViewer)) { 323 throw new IllegalArgumentException ("This content provider can only be used with TreeViewers"); } 325 TreeViewer newTreeViewer = (TreeViewer) viewer; 326 327 if (newTreeViewer != treeViewer) { 328 if (treeViewer != null) { 329 treeViewer.removeTreeListener(expandListener); 330 } 331 332 this.treeViewer = newTreeViewer; 333 if (newTreeViewer != null) { 334 newTreeViewer.addTreeListener(expandListener); 335 } 336 } 337 } 338 339 public Object [] getChildren(Object parentElement) { 340 Set result = getNode(parentElement).getChildren(); 341 342 addParent(parentElement, result); 343 344 return result.toArray(); 345 } 346 347 private TreeNode getNode(Object parentElement) { 348 TreeNode result = (TreeNode)mapElementToTreeNode.get(parentElement); 349 if (result == null) { 350 result = new TreeNode(parentElement, this); 351 mapElementToTreeNode.put(parentElement, result); 352 elements.fireSetChange(Diffs.createSetDiff(Collections.singleton(parentElement), 353 Collections.EMPTY_SET)); 354 } 355 return result; 356 } 357 358 public Object getParent(Object element) { 359 Object result = getNode(element).getParent(); 360 if (result == null && rootParentProvider != null) { 361 result = rootParentProvider.getParent(element); 362 } 363 return result; 364 } 365 366 public boolean hasChildren(Object element) { 367 return getNode(element).shouldShowPlus(); 368 } 369 370 public Object [] getElements(Object inputElement) { 371 return getChildren(inputElement); 372 } 373 374 377 public IObservableSet getKnownElements() { 378 return elements; 379 } 380 381 void changeStale(int staleDelta) { 382 staleCount += staleDelta; 383 processPrefetches(); 384 elements.setStale(staleCount != 0); 385 } 386 387 390 public TreeViewer getViewer() { 391 return treeViewer; 392 } 393 394 398 public boolean isDirty(Object element) { 399 return false; 400 } 401 402 void enqueuePrefetch(TreeNode node) { 403 if (maxPrefetches > 0 || maxPrefetches == -1) { 404 if (staleCount == 0) { 405 node.getChildren(); 411 } else { 412 enqueuedPrefetches.add(node); 413 while (maxPrefetches >= 0 && enqueuedPrefetches.size() > maxPrefetches) { 414 enqueuedPrefetches.removeFirst(); 415 } 416 } 417 } 418 } 419 420 private void processPrefetches() { 421 while (staleCount == 0 && !enqueuedPrefetches.isEmpty()) { 422 TreeNode next = (TreeNode)enqueuedPrefetches.removeLast(); 423 424 if (!next.isDisposed()) { 427 next.prefetch(); 428 } 429 } 430 } 431 432 public Object [] getChildren(TreePath parentPath) { 433 return getChildren(parentPath.getLastSegment()); 434 } 435 436 public TreePath[] getParents(Object element) { 437 441 List parentPaths = computeParents(element, new HashSet ()); 442 443 446 List result = new ArrayList (); 447 448 for (Iterator iterator = parentPaths.iterator(); iterator.hasNext();) { 449 List nextPath = (List ) iterator.next(); 450 451 LinkedList resultPath = new LinkedList (); 452 resultPath.addAll(nextPath); 453 Object nextParent = resultPath.isEmpty() ? element : resultPath.getFirst(); 454 for(;nextParent != null;) { 455 if (rootParentProvider != null) { 456 nextParent = rootParentProvider.getParent(nextParent); 457 if (nextParent != null) { 458 resultPath.addFirst(nextParent); 459 } 460 } else { 461 nextParent = null; 462 } 463 } 464 465 result.add(new TreePath(resultPath.toArray())); 466 } 467 468 if (result.isEmpty() && rootParentProvider != null) { 469 Object nextParent = rootParentProvider.getParent(element); 470 if (nextParent != null) { 471 LinkedList resultPath = new LinkedList (); 472 while (nextParent != null) { 473 resultPath.addFirst(nextParent); 474 nextParent = rootParentProvider.getParent(nextParent); 475 } 476 477 result.add(new TreePath(resultPath.toArray())); 478 } 479 480 } 481 482 return (TreePath[]) result.toArray(new TreePath[result.size()]); 483 } 484 485 491 private List computeParents(Object node, HashSet toIgnore) { 492 List result = new ArrayList (); 493 boolean containedNode = toIgnore.add(node); 494 495 TreeNode tn = getNode(node); 496 497 HashSet parents = new HashSet (); 498 parents.addAll(tn.getParents()); 499 parents.removeAll(toIgnore); 500 if (parents.isEmpty()) { 501 ArrayList newPath = new ArrayList (); 502 result.add(newPath); 503 } else { 504 for (Iterator iterator = parents.iterator(); iterator.hasNext();) { 505 Object parent = iterator.next(); 506 507 List parentPaths = computeParents(parent, toIgnore); 508 509 for (Iterator iterator2 = parentPaths.iterator(); iterator2 510 .hasNext();) { 511 List parentPath = (List ) iterator2.next(); 512 513 parentPath.add(parent); 514 result.add(parentPath); 515 } 516 } 517 } 518 519 if (containedNode) { 520 toIgnore.remove(node); 521 } 522 return result; 523 } 524 525 public boolean hasChildren(TreePath path) { 526 return hasChildren(path.getLastSegment()); 527 } 528 } 529 | Popular Tags |