1 11 12 package org.eclipse.ui.internal.navigator; 13 14 import java.util.ArrayList ; 15 import java.util.Arrays ; 16 import java.util.HashMap ; 17 import java.util.HashSet ; 18 import java.util.Iterator ; 19 import java.util.List ; 20 import java.util.Map ; 21 import java.util.Set ; 22 import java.util.TreeMap ; 23 24 import org.eclipse.core.runtime.Platform; 25 import org.eclipse.jface.viewers.IStructuredSelection; 26 import org.eclipse.jface.viewers.ITreeContentProvider; 27 import org.eclipse.jface.viewers.ITreePathContentProvider; 28 import org.eclipse.jface.viewers.ITreeSelection; 29 import org.eclipse.jface.viewers.StructuredViewer; 30 import org.eclipse.jface.viewers.TreePath; 31 import org.eclipse.swt.events.DisposeEvent; 32 import org.eclipse.swt.events.DisposeListener; 33 import org.eclipse.swt.widgets.Display; 34 import org.eclipse.ui.ISaveablesLifecycleListener; 35 import org.eclipse.ui.ISaveablesSource; 36 import org.eclipse.ui.Saveable; 37 import org.eclipse.ui.SaveablesLifecycleEvent; 38 import org.eclipse.ui.internal.navigator.VisibilityAssistant.VisibilityListener; 39 import org.eclipse.ui.internal.navigator.extensions.ExtensionPriorityComparator; 40 import org.eclipse.ui.internal.navigator.extensions.NavigatorContentDescriptor; 41 import org.eclipse.ui.internal.navigator.extensions.NavigatorContentExtension; 42 import org.eclipse.ui.navigator.INavigatorContentDescriptor; 43 import org.eclipse.ui.navigator.INavigatorSaveablesService; 44 import org.eclipse.ui.navigator.SaveablesProvider; 45 import org.osgi.framework.Bundle; 46 import org.osgi.framework.BundleEvent; 47 48 58 public class NavigatorSaveablesService implements INavigatorSaveablesService, VisibilityListener { 59 60 private NavigatorContentService contentService; 61 62 private static List instances = new ArrayList (); 63 64 67 public NavigatorSaveablesService(NavigatorContentService contentService) { 68 this.contentService = contentService; 69 } 70 71 private static void addInstance(NavigatorSaveablesService saveablesService) { 72 synchronized (instances) { 73 instances.add(saveablesService); 74 } 75 } 76 77 private static void removeInstance( 78 NavigatorSaveablesService saveablesService) { 79 synchronized (instances) { 80 instances.remove(saveablesService); 81 } 82 } 83 84 87 static void bundleChanged(BundleEvent event) { 88 synchronized(instances) { 89 if (event.getType() == BundleEvent.STARTED) { 90 for (Iterator it = instances.iterator(); it.hasNext();) { 92 NavigatorSaveablesService instance = (NavigatorSaveablesService) it 93 .next(); 94 instance.handleBundleStarted(event.getBundle() 95 .getSymbolicName()); 96 } 97 } else if (event.getType() == BundleEvent.STOPPED) { 98 for (Iterator it = instances.iterator(); it.hasNext();) { 100 NavigatorSaveablesService instance = (NavigatorSaveablesService) it 101 .next(); 102 instance.handleBundleStopped(event.getBundle() 103 .getSymbolicName()); 104 } 105 } 106 } 107 } 108 109 private class LifecycleListener implements ISaveablesLifecycleListener { 110 public void handleLifecycleEvent(SaveablesLifecycleEvent event) { 111 Saveable[] saveables = event.getSaveables(); 112 switch (event.getEventType()) { 113 case SaveablesLifecycleEvent.POST_OPEN: 114 recomputeSaveablesAndNotify(false, null); 115 break; 116 case SaveablesLifecycleEvent.POST_CLOSE: 117 recomputeSaveablesAndNotify(false, null); 118 break; 119 case SaveablesLifecycleEvent.DIRTY_CHANGED: 120 Saveable[] shownSaveables = getShownSaveables(saveables); 121 if (shownSaveables.length > 0) { 122 outsideListener 123 .handleLifecycleEvent(new SaveablesLifecycleEvent( 124 saveablesSource, 125 SaveablesLifecycleEvent.DIRTY_CHANGED, 126 shownSaveables, false)); 127 } 128 break; 129 } 130 } 131 } 132 133 private Saveable[] currentSaveables; 134 135 private ISaveablesLifecycleListener outsideListener; 136 137 private ISaveablesLifecycleListener saveablesLifecycleListener = new LifecycleListener(); 138 139 private ISaveablesSource saveablesSource; 140 141 private StructuredViewer viewer; 142 143 private SaveablesProvider[] saveablesProviders; 144 145 private DisposeListener disposeListener = new DisposeListener() { 146 147 public void widgetDisposed(DisposeEvent e) { 148 synchronized (instances) { 150 synchronized (NavigatorSaveablesService.this) { 151 if (saveablesProviders != null) { 152 for (int i = 0; i < saveablesProviders.length; i++) { 153 saveablesProviders[i].dispose(); 154 } 155 } 156 removeInstance(NavigatorSaveablesService.this); 157 contentService = null; 158 currentSaveables = null; 159 outsideListener = null; 160 saveablesLifecycleListener = null; 161 saveablesSource = null; 162 viewer = null; 163 saveablesProviders = null; 164 disposeListener = null; 165 } 166 } 167 } 168 }; 169 170 private Map inactivePluginsWithSaveablesProviders; 171 172 176 private Map saveablesProviderMap; 177 178 187 public void init(final ISaveablesSource saveablesSource, 188 final StructuredViewer viewer, 189 ISaveablesLifecycleListener outsideListener) { 190 synchronized (instances) { 192 synchronized (this) { 199 this.saveablesSource = saveablesSource; 200 this.viewer = viewer; 201 this.outsideListener = outsideListener; 202 currentSaveables = computeSaveables(); 203 addInstance(this); 205 } 206 } 207 viewer.getControl().addDisposeListener(disposeListener); 208 } 209 210 215 private Saveable[] computeSaveables() { 216 ITreeContentProvider contentProvider = (ITreeContentProvider) viewer 217 .getContentProvider(); 218 boolean isTreepathContentProvider = contentProvider instanceof ITreePathContentProvider; 219 Object viewerInput = viewer.getInput(); 220 List result = new ArrayList (); 221 Set roots = new HashSet (Arrays.asList(contentProvider 222 .getElements(viewerInput))); 223 SaveablesProvider[] saveablesProviders = getSaveablesProviders(); 224 for (int i = 0; i < saveablesProviders.length; i++) { 225 SaveablesProvider saveablesProvider = saveablesProviders[i]; 226 Saveable[] saveables = saveablesProvider.getSaveables(); 227 for (int j = 0; j < saveables.length; j++) { 228 Saveable saveable = saveables[j]; 229 Object [] elements = saveablesProvider.getElements(saveable); 230 boolean foundRoot = false; 234 for (int k = 0; !foundRoot && k < elements.length; k++) { 235 Object element = elements[k]; 236 if (roots.contains(element)) { 237 result.add(saveable); 238 foundRoot = true; 239 } else if (isTreepathContentProvider) { 240 ITreePathContentProvider treePathContentProvider = (ITreePathContentProvider) contentProvider; 241 TreePath[] parentPaths = treePathContentProvider.getParents(element); 242 for (int l = 0; !foundRoot && l < parentPaths.length; l++) { 243 TreePath parentPath = parentPaths[l]; 244 for (int m = 0; !foundRoot && m < parentPath.getSegmentCount(); m++) { 245 if (roots.contains(parentPath.getSegment(m))) { 246 result.add(saveable); 247 foundRoot = true; 248 } 249 } 250 } 251 } else { 252 while (!foundRoot && element != null) { 253 if (roots.contains(element)) { 254 result.add(saveable); 257 foundRoot = true; 258 } else { 259 element = contentProvider.getParent(element); 260 } 261 } 262 } 263 } 264 } 265 } 266 return (Saveable[]) result.toArray(new Saveable[result.size()]); 267 } 268 269 public synchronized Saveable[] getActiveSaveables() { 270 ITreeContentProvider contentProvider = (ITreeContentProvider) viewer 271 .getContentProvider(); 272 IStructuredSelection selection = (IStructuredSelection) viewer 273 .getSelection(); 274 if (selection instanceof ITreeSelection) { 275 return getActiveSaveablesFromTreeSelection((ITreeSelection) selection); 276 } else if (contentProvider instanceof ITreePathContentProvider) { 277 return getActiveSaveablesFromTreePathProvider(selection, (ITreePathContentProvider) contentProvider); 278 } else { 279 return getActiveSaveablesFromTreeProvider(selection, contentProvider); 280 } 281 } 282 283 287 private Saveable[] getActiveSaveablesFromTreeSelection( 288 ITreeSelection selection) { 289 Set result = new HashSet (); 290 TreePath[] paths = selection.getPaths(); 291 for (int i = 0; i < paths.length; i++) { 292 TreePath path = paths[i]; 293 Saveable saveable = findSaveable(path); 294 if (saveable != null) { 295 result.add(saveable); 296 } 297 } 298 return (Saveable[]) result.toArray(new Saveable[result.size()]); 299 } 300 301 306 private Saveable[] getActiveSaveablesFromTreePathProvider( 307 IStructuredSelection selection, ITreePathContentProvider provider) { 308 Set result = new HashSet (); 309 for (Iterator it = selection.iterator(); it.hasNext();) { 310 Object element = it.next(); 311 Saveable saveable = getSaveable(element); 312 if (saveable != null) { 313 result.add(saveable); 314 } else { 315 TreePath[] paths = provider.getParents(element); 316 saveable = findSaveable(paths); 317 if (saveable != null) { 318 result.add(saveable); 319 } 320 } 321 } 322 return (Saveable[]) result.toArray(new Saveable[result.size()]); 323 } 324 325 330 private Saveable[] getActiveSaveablesFromTreeProvider( 331 IStructuredSelection selection, ITreeContentProvider contentProvider) { 332 Set result = new HashSet (); 333 for (Iterator it = selection.iterator(); it.hasNext();) { 334 Object element = it.next(); 335 Saveable saveable = findSaveable(element, contentProvider); 336 if (saveable != null) { 337 result.add(saveable); 338 } 339 } 340 return (Saveable[]) result.toArray(new Saveable[result.size()]); 341 } 342 343 348 private Saveable findSaveable(Object element, 349 ITreeContentProvider contentProvider) { 350 while (element != null) { 351 Saveable saveable = getSaveable(element); 352 if (saveable != null) { 353 return saveable; 354 } 355 element = contentProvider.getParent(element); 356 } 357 return null; 358 } 359 360 364 private Saveable findSaveable(TreePath[] paths) { 365 for (int i = 0; i < paths.length; i++) { 366 Saveable saveable = findSaveable(paths[i]); 367 if (saveable != null) { 368 return saveable; 369 } 370 } 371 return null; 372 } 373 374 378 private Saveable findSaveable(TreePath path) { 379 int count = path.getSegmentCount(); 380 for (int j = count - 1; j >= 0; j--) { 381 Object parent = path.getSegment(j); 382 Saveable saveable = getSaveable(parent); 383 if (saveable != null) { 384 return saveable; 385 } 386 } 387 return null; 388 } 389 390 394 private Saveable getSaveable(Object element) { 395 if (saveablesProviderMap==null) { 396 getSaveablesProviders(); 398 } 399 for(Iterator sItr = saveablesProviderMap.keySet().iterator(); sItr.hasNext();) { 400 NavigatorContentDescriptor descriptor = (NavigatorContentDescriptor) sItr.next(); 401 if(descriptor.isTriggerPoint(element) || descriptor.isPossibleChild(element)) { 402 SaveablesProvider provider = (SaveablesProvider) saveablesProviderMap.get(descriptor); 403 Saveable saveable = provider.getSaveable(element); 404 if(saveable != null) { 405 return saveable; 406 } 407 } 408 } 409 return null; 410 } 411 412 415 public synchronized Saveable[] getSaveables() { 416 return currentSaveables; 417 } 418 419 422 private SaveablesProvider[] getSaveablesProviders() { 423 if (saveablesProviders == null) { 425 inactivePluginsWithSaveablesProviders = new HashMap (); 426 saveablesProviderMap = new TreeMap (ExtensionPriorityComparator.INSTANCE); 427 INavigatorContentDescriptor[] descriptors = contentService 428 .getActiveDescriptorsWithSaveables(); 429 List result = new ArrayList (); 430 for (int i = 0; i < descriptors.length; i++) { 431 NavigatorContentDescriptor descriptor = (NavigatorContentDescriptor) descriptors[i]; 432 String pluginId = ((NavigatorContentDescriptor) descriptor) 433 .getContribution().getPluginId(); 434 if (Platform.getBundle(pluginId).getState() != Bundle.ACTIVE) { 435 List inactiveDescriptors = (List ) inactivePluginsWithSaveablesProviders 436 .get(pluginId); 437 if (inactiveDescriptors == null) { 438 inactiveDescriptors = new ArrayList (); 439 inactivePluginsWithSaveablesProviders.put(pluginId, 440 inactiveDescriptors); 441 } 442 inactiveDescriptors.add(descriptor); 443 } else { 444 SaveablesProvider saveablesProvider = createSaveablesProvider(descriptor); 445 if (saveablesProvider != null) { 446 saveablesProvider.init(saveablesLifecycleListener); 447 result.add(saveablesProvider); 448 saveablesProviderMap.put(descriptor, saveablesProvider); 449 } 450 } 451 } 452 saveablesProviders = (SaveablesProvider[]) result 453 .toArray(new SaveablesProvider[result.size()]); 454 } 455 return saveablesProviders; 456 } 457 458 462 private SaveablesProvider createSaveablesProvider(NavigatorContentDescriptor descriptor) { 463 NavigatorContentExtension extension = contentService 464 .getExtension(descriptor, true); 465 ITreeContentProvider contentProvider = extension 466 .getContentProvider(); 467 468 return (SaveablesProvider)AdaptabilityUtility.getAdapter(contentProvider, SaveablesProvider.class); 469 } 470 471 private Saveable[] getShownSaveables(Saveable[] saveables) { 472 Set result = new HashSet (Arrays.asList(currentSaveables)); 473 result.retainAll(Arrays.asList(saveables)); 474 return (Saveable[]) result.toArray(new Saveable[result.size()]); 475 } 476 477 private void recomputeSaveablesAndNotify(boolean recomputeProviders, 478 String startedBundleIdOrNull) { 479 if (recomputeProviders && startedBundleIdOrNull == null 480 && saveablesProviders != null) { 481 for (int i = 0; i < saveablesProviders.length; i++) { 485 saveablesProviders[i].dispose(); 486 } 487 saveablesProviders = null; 488 } else if (startedBundleIdOrNull != null){ 489 if(inactivePluginsWithSaveablesProviders.containsKey(startedBundleIdOrNull)) { 490 updateSaveablesProviders(startedBundleIdOrNull); 491 } 492 } 493 Set oldSaveables = new HashSet (Arrays.asList(currentSaveables)); 494 currentSaveables = computeSaveables(); 495 Set newSaveables = new HashSet (Arrays.asList(currentSaveables)); 496 final Set removedSaveables = new HashSet (oldSaveables); 497 removedSaveables.removeAll(newSaveables); 498 final Set addedSaveables = new HashSet (newSaveables); 499 addedSaveables.removeAll(oldSaveables); 500 if (addedSaveables.size() > 0) { 501 Display.getDefault().asyncExec(new Runnable () { 502 public void run() { 503 if (saveablesSource == null) { 506 return; 507 } 508 outsideListener.handleLifecycleEvent(new SaveablesLifecycleEvent( 509 saveablesSource, SaveablesLifecycleEvent.POST_OPEN, 510 (Saveable[]) addedSaveables 511 .toArray(new Saveable[addedSaveables.size()]), 512 false)); 513 } 514 }); 515 } 516 if (removedSaveables.size() > 0) { 520 Display.getDefault().asyncExec(new Runnable () { 521 public void run() { 522 if (saveablesSource == null) { 525 return; 526 } 527 outsideListener 528 .handleLifecycleEvent(new SaveablesLifecycleEvent( 529 saveablesSource, 530 SaveablesLifecycleEvent.PRE_CLOSE, 531 (Saveable[]) removedSaveables 532 .toArray(new Saveable[removedSaveables 533 .size()]), true)); 534 outsideListener 535 .handleLifecycleEvent(new SaveablesLifecycleEvent( 536 saveablesSource, 537 SaveablesLifecycleEvent.POST_CLOSE, 538 (Saveable[]) removedSaveables 539 .toArray(new Saveable[removedSaveables 540 .size()]), false)); 541 } 542 }); 543 } 544 } 545 546 549 private void updateSaveablesProviders(String startedBundleId) { 550 List result = new ArrayList (Arrays.asList(saveablesProviders)); 551 List descriptors = (List ) inactivePluginsWithSaveablesProviders 552 .get(startedBundleId); 553 for (Iterator it = descriptors.iterator(); it.hasNext();) { 554 NavigatorContentDescriptor descriptor = (NavigatorContentDescriptor) it 555 .next(); 556 SaveablesProvider saveablesProvider = createSaveablesProvider(descriptor); 557 if (saveablesProvider != null) { 558 saveablesProvider.init(saveablesLifecycleListener); 559 result.add(saveablesProvider); 560 saveablesProviderMap.put(descriptor, saveablesProvider); 561 } 562 } 563 saveablesProviders = (SaveablesProvider[]) result 564 .toArray(new SaveablesProvider[result.size()]); 565 } 566 567 570 private synchronized void handleBundleStarted(String symbolicName) { 571 if (saveablesSource != null) { 574 if (inactivePluginsWithSaveablesProviders.containsKey(symbolicName)) { 575 recomputeSaveablesAndNotify(true, symbolicName); 576 } 577 } 578 } 579 580 583 private synchronized void handleBundleStopped(String symbolicName) { 584 if (saveablesSource != null) { 587 recomputeSaveablesAndNotify(true, null); 588 } 589 } 590 591 594 public synchronized void onVisibilityOrActivationChange() { 595 if (saveablesSource != null) { 598 recomputeSaveablesAndNotify(true, null); 599 } 600 } 601 602 } 603 | Popular Tags |