1 11 12 package org.eclipse.ui.internal.menus; 13 14 import java.util.ArrayList ; 15 import java.util.HashMap ; 16 import java.util.HashSet ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Map ; 20 import java.util.Set ; 21 22 import org.eclipse.core.expressions.Expression; 23 import org.eclipse.core.expressions.IEvaluationContext; 24 import org.eclipse.core.runtime.ISafeRunnable; 25 import org.eclipse.core.runtime.SafeRunner; 26 import org.eclipse.jface.action.ContributionItem; 27 import org.eclipse.jface.action.ContributionManager; 28 import org.eclipse.jface.action.IContributionItem; 29 import org.eclipse.jface.action.IContributionManager; 30 import org.eclipse.jface.action.ICoolBarManager; 31 import org.eclipse.jface.action.IMenuListener; 32 import org.eclipse.jface.action.IMenuManager; 33 import org.eclipse.jface.action.IToolBarManager; 34 import org.eclipse.jface.action.MenuManager; 35 import org.eclipse.jface.action.ToolBarContributionItem; 36 import org.eclipse.jface.action.ToolBarManager; 37 import org.eclipse.jface.internal.provisional.action.IToolBarContributionItem; 38 import org.eclipse.jface.util.IPropertyChangeListener; 39 import org.eclipse.jface.util.PropertyChangeEvent; 40 import org.eclipse.swt.widgets.Control; 41 import org.eclipse.ui.ISourceProvider; 42 import org.eclipse.ui.IWorkbench; 43 import org.eclipse.ui.IWorkbenchWindow; 44 import org.eclipse.ui.PlatformUI; 45 import org.eclipse.ui.activities.ActivityManagerEvent; 46 import org.eclipse.ui.activities.IActivityManagerListener; 47 import org.eclipse.ui.activities.IIdentifier; 48 import org.eclipse.ui.activities.IIdentifierListener; 49 import org.eclipse.ui.activities.IdentifierEvent; 50 import org.eclipse.ui.internal.WorkbenchPlugin; 51 import org.eclipse.ui.internal.WorkbenchWindow; 52 import org.eclipse.ui.internal.expressions.AlwaysEnabledExpression; 53 import org.eclipse.ui.internal.layout.LayoutUtil; 54 import org.eclipse.ui.internal.services.IEvaluationReference; 55 import org.eclipse.ui.internal.services.IEvaluationService; 56 import org.eclipse.ui.internal.util.Util; 57 import org.eclipse.ui.menus.AbstractContributionFactory; 58 import org.eclipse.ui.services.IServiceLocator; 59 60 71 public final class WorkbenchMenuService extends InternalMenuService { 72 73 79 private final class ContributionItemUpdater implements 80 IPropertyChangeListener, IIdentifierListener { 81 82 private final IContributionItem item; 83 private IIdentifier identifier; 84 private boolean lastExpressionResult = true; 85 86 private ContributionItemUpdater(IContributionItem item, 87 IIdentifier identifier) { 88 this.item = item; 89 if (identifier != null) { 90 this.identifier = identifier; 91 this.identifier.addIdentifierListener(this); 92 updateVisibility(); } 95 } 96 97 102 public void propertyChange(PropertyChangeEvent event) { 103 if (event.getProperty() == PROP_VISIBLE) { 104 if (event.getNewValue() != null) { 105 this.lastExpressionResult = ((Boolean ) event.getNewValue()) 106 .booleanValue(); 107 } else { 108 this.lastExpressionResult = false; 109 } 110 updateVisibility(); 111 } 112 } 113 114 private void updateVisibility() { 115 boolean visible = identifier != null ? (identifier.isEnabled() && lastExpressionResult) 116 : lastExpressionResult; 117 item.setVisible(visible); 118 119 IContributionManager parent = null; 120 if (item instanceof ContributionItem) { 121 parent = ((ContributionItem) item).getParent(); 122 123 } else if (item instanceof MenuManager) { 124 parent = ((MenuManager) item).getParent(); 125 } 126 if (parent != null) { 127 parent.markDirty(); 128 managersAwaitingUpdates.add(parent); 129 } 130 } 131 132 137 public void identifierChanged(IdentifierEvent identifierEvent) { 138 updateVisibility(); 139 } 140 141 144 public void dispose() { 145 identifier.removeIdentifierListener(this); 146 } 147 } 148 149 152 private static final String PROP_VISIBLE = "visible"; 154 157 private final MenuPersistence menuPersistence; 158 159 163 private IEvaluationService evaluationService; 164 165 private IPropertyChangeListener serviceListener; 166 167 170 private IServiceLocator serviceLocator; 171 172 private IActivityManagerListener activityManagerListener; 173 174 178 public WorkbenchMenuService(IServiceLocator serviceLocator) { 179 this.menuPersistence = new MenuPersistence(this); 180 this.serviceLocator = serviceLocator; 181 evaluationService = (IEvaluationService) serviceLocator 182 .getService(IEvaluationService.class); 183 evaluationService.addServiceListener(getServiceListener()); 184 ((IWorkbench) serviceLocator.getService(IWorkbench.class)) 185 .getActivitySupport().getActivityManager() 186 .addActivityManagerListener(getActivityManagerListener()); 187 } 188 189 192 private IActivityManagerListener getActivityManagerListener() { 193 if (activityManagerListener == null) { 194 activityManagerListener = new IActivityManagerListener() { 195 196 public void activityManagerChanged( 197 ActivityManagerEvent activityManagerEvent) { 198 if (activityManagerEvent.haveEnabledActivityIdsChanged()) { 199 updateManagers(); } 203 204 } 205 }; 206 } 207 return activityManagerListener; 208 } 209 210 213 private IPropertyChangeListener getServiceListener() { 214 if (serviceListener == null) { 215 serviceListener = new IPropertyChangeListener() { 216 public void propertyChange(PropertyChangeEvent event) { 217 if (event.getProperty().equals( 218 IEvaluationService.PROP_NOTIFYING)) { 219 if (!((Boolean ) event.getNewValue()).booleanValue()) { 220 updateManagers(); 224 } 225 } 226 } 227 }; 228 } 229 return serviceListener; 230 } 231 232 private void updateManagers() { 233 Object [] managers = managersAwaitingUpdates.toArray(); 234 managersAwaitingUpdates.clear(); 235 for (int i = 0; i < managers.length; i++) { 236 IContributionManager mgr = (IContributionManager) managers[i]; 237 mgr.update(true); 238 if (mgr instanceof ToolBarManager) { 239 if (!updateCoolBar((ToolBarManager) mgr)) { 240 updateTrim((ToolBarManager) mgr); 241 } 242 } else if (mgr instanceof MenuManager) { 243 IContributionManager parent = ((MenuManager) mgr).getParent(); 244 if (parent != null) { 245 parent.update(true); 246 } 247 } 248 } 249 } 250 251 private void updateTrim(ToolBarManager mgr) { 252 Control control = mgr.getControl(); 253 if (control == null || control.isDisposed()) { 254 return; 255 } 256 LayoutUtil.resize(control); 257 } 258 259 private boolean updateCoolBar(ToolBarManager mgr) { 260 IWorkbenchWindow[] windows = PlatformUI.getWorkbench() 261 .getWorkbenchWindows(); 262 for (int i = 0; i < windows.length; i++) { 263 WorkbenchWindow window = (WorkbenchWindow) windows[i]; 264 ICoolBarManager cb = window.getCoolBarManager2(); 265 if (cb != null) { 266 IContributionItem[] items = cb.getItems(); 267 for (int j = 0; j < items.length; j++) { 268 if (items[j] instanceof ToolBarContributionItem) { 269 IToolBarManager tbm = ((ToolBarContributionItem) items[j]) 270 .getToolBarManager(); 271 if (mgr == tbm) { 272 cb.update(true); 273 return true; 274 } 275 } 276 } 277 } 278 } 279 return false; 280 } 281 282 public final void addSourceProvider(final ISourceProvider provider) { 283 } 285 286 public final void dispose() { 287 menuPersistence.dispose(); 288 Iterator i = evaluationsByItem.values().iterator(); 289 while (i.hasNext()) { 290 IEvaluationReference ref = (IEvaluationReference) i.next(); 291 evaluationService.removeEvaluationListener(ref); 292 } 293 evaluationsByItem.clear(); 294 managersAwaitingUpdates.clear(); 295 if (serviceListener != null) { 296 evaluationService.removeServiceListener(serviceListener); 297 serviceListener = null; 298 } 299 } 300 301 public final void readRegistry() { 302 menuPersistence.read(); 303 } 304 305 public final void removeSourceProvider(final ISourceProvider provider) { 306 } 308 309 private Map uriToManager = new HashMap (); 313 314 private Map contributionManagerTracker = new HashMap (); 315 316 private IMenuListener menuTrackerListener; 317 318 private Map evaluationsByItem = new HashMap (); 319 320 private Map activityListenersByItem = new HashMap (); 321 322 private Set managersAwaitingUpdates = new HashSet (); 323 324 335 private String getIdFromURI(MenuLocationURI uri) { 336 return uri.getScheme() + ":" + uri.getPath(); } 338 339 public List getAdditionsForURI(MenuLocationURI uri) { 340 if (uri == null) 341 return null; 342 343 List caches = (List ) uriToManager.get(getIdFromURI(uri)); 344 345 if (caches == null) { 347 caches = new ArrayList (); 348 uriToManager.put(getIdFromURI(uri), caches); 349 } 350 351 return caches; 352 } 353 354 359 public void addContributionFactory(AbstractContributionFactory factory) { 360 if (factory == null || factory.getLocation() == null) 361 return; 362 363 MenuLocationURI uri = new MenuLocationURI(factory.getLocation()); 364 String cacheId = getIdFromURI(uri); 365 List caches = (List ) uriToManager.get(cacheId); 366 367 if (caches == null) { 369 caches = new ArrayList (); 370 uriToManager.put(cacheId, caches); 371 } 372 caches.add(factory); 373 } 374 375 380 public void removeContributionFactory(AbstractContributionFactory factory) { 381 if (factory == null || factory.getLocation() == null) 382 return; 383 384 MenuLocationURI uri = new MenuLocationURI(factory.getLocation()); 385 String cacheId = getIdFromURI(uri); 386 List caches = (List ) uriToManager.get(cacheId); 387 if (caches != null) { 388 caches.remove(factory); 389 } 390 } 391 392 private boolean processAdditions(final IServiceLocator serviceLocatorToUse, 393 Expression restriction, final ContributionManager mgr, 394 final AbstractContributionFactory cache, final Set itemsAdded) { 395 final int idx = getInsertionIndex(mgr, cache.getLocation()); 396 if (idx == -1) 397 return false; 399 final ContributionRoot ciList = new ContributionRoot(this, restriction, 401 cache.getNamespace()); 402 403 ISafeRunnable run = new ISafeRunnable() { 404 405 public void handleException(Throwable exception) { 406 408 } 409 410 public void run() throws Exception { 411 int insertionIndex = idx; 412 cache.createContributionItems(serviceLocatorToUse, ciList); 413 414 if (ciList.getItems().size() > 0) { 416 track(mgr, cache, ciList); 417 for (Iterator ciIter = ciList.getItems().iterator(); ciIter 418 .hasNext();) { 419 IContributionItem ici = (IContributionItem) ciIter 420 .next(); 421 if (ici.getId() != null) { 422 itemsAdded.add(ici.getId()); 423 } 424 final int oldSize = mgr.getSize(); 425 mgr.insert(insertionIndex, ici); 426 if (mgr.getSize() > oldSize) 427 insertionIndex++; 428 } 429 } 430 } 431 }; 432 SafeRunner.run(run); 433 434 return true; 435 } 436 437 442 private void track(ContributionManager mgr, 443 AbstractContributionFactory cache, ContributionRoot ciList) { 444 List contributions = (List ) contributionManagerTracker.get(mgr); 445 if (contributions == null) { 446 contributions = new ArrayList (); 447 contributionManagerTracker.put(mgr, contributions); 448 if (mgr instanceof IMenuManager) { 449 IMenuManager m = (IMenuManager) mgr; 450 if (m.getRemoveAllWhenShown()) { 451 m.addMenuListener(getMenuTrackerListener()); 452 } 453 } 454 } 455 contributions.add(ciList); 456 } 457 458 461 private IMenuListener getMenuTrackerListener() { 462 if (menuTrackerListener == null) { 463 menuTrackerListener = new IMenuListener() { 464 public void menuAboutToShow(IMenuManager manager) { 465 sweepContributions(manager); 466 } 467 }; 468 } 469 return menuTrackerListener; 470 } 471 472 475 protected void sweepContributions(IMenuManager manager) { 476 List contributions = (List ) contributionManagerTracker.get(manager); 477 if (contributions == null) { 478 return; 479 } 480 Iterator i = contributions.iterator(); 481 while (i.hasNext()) { 482 final ContributionRoot items = (ContributionRoot) i.next(); 483 boolean removed = false; 484 Iterator j = items.getItems().iterator(); 485 while (j.hasNext()) { 486 IContributionItem item = (IContributionItem) j.next(); 487 if (item instanceof ContributionItem 488 && ((ContributionItem) item).getParent() == null) { 489 removed = true; 490 releaseItem(item); 491 } 492 } 493 if (removed) { 494 releaseCache(items); 495 i.remove(); 496 } 497 } 498 } 499 500 503 private void releaseCache(final ContributionRoot items) { 504 items.release(); 505 } 506 507 513 public void populateContributionManager(ContributionManager mgr, String uri) { 514 populateContributionManager(serviceLocator, null, mgr, uri, true); 515 } 516 517 public void populateContributionManager( 518 IServiceLocator serviceLocatorToUse, Expression restriction, 519 ContributionManager mgr, String uri, boolean recurse) { 520 MenuLocationURI contributionLocation = new MenuLocationURI(uri); 521 List additionCaches = getAdditionsForURI(contributionLocation); 522 523 List retryList = new ArrayList (); 524 Set itemsAdded = new HashSet (); 525 for (Iterator iterator = additionCaches.iterator(); iterator.hasNext();) { 526 AbstractContributionFactory cache = (AbstractContributionFactory) iterator 527 .next(); 528 if (!processAdditions(serviceLocatorToUse, restriction, mgr, cache, 529 itemsAdded)) { 530 retryList.add(cache); 531 } 532 } 533 534 boolean done = retryList.size() == 0; 539 while (!done) { 540 List curRetry = new ArrayList (retryList); 542 int retryCount = retryList.size(); 543 retryList.clear(); 544 545 for (Iterator iterator = curRetry.iterator(); iterator.hasNext();) { 547 AbstractContributionFactory cache = (AbstractContributionFactory) iterator 548 .next(); 549 if (!processAdditions(serviceLocatorToUse, restriction, mgr, 550 cache, itemsAdded)) 551 retryList.add(cache); 552 } 553 554 done = (retryList.size() == 0) || (retryList.size() == retryCount); 557 } 558 559 IContributionItem[] curItems = mgr.getItems(); 561 for (int i = 0; i < curItems.length; i++) { 562 if (curItems[i] instanceof ContributionManager) { 563 String id = curItems[i].getId(); 564 if (id != null && id.length() > 0 565 && (recurse || itemsAdded.contains(id))) { 566 populateContributionManager(serviceLocatorToUse, 567 restriction, (ContributionManager) curItems[i], 568 contributionLocation.getScheme() + ":" + id, true); } 570 } else if (curItems[i] instanceof IToolBarContributionItem) { 571 IToolBarContributionItem tbci = (IToolBarContributionItem) curItems[i]; 572 if (tbci.getId() != null && tbci.getId().length() > 0 573 && (recurse || itemsAdded.contains(tbci.getId()))) { 574 populateContributionManager(serviceLocatorToUse, 575 restriction, (ContributionManager) tbci 576 .getToolBarManager(), contributionLocation 577 .getScheme() 578 + ":" + tbci.getId(), true); } 580 } 581 } 582 } 583 584 589 private int getInsertionIndex(ContributionManager mgr, String location) { 590 MenuLocationURI uri = new MenuLocationURI(location); 591 String query = uri.getQuery(); 592 593 int additionsIndex = -1; 594 595 if (query.length() == 0 || query.equals("after=additions")) { additionsIndex = mgr.indexOf("additions"); if (additionsIndex == -1) 600 additionsIndex = mgr.getItems().length; 601 else 602 ++additionsIndex; 603 } else { 604 String [] queryParts = Util.split(query, '='); 606 if (queryParts[1].length() > 0) { 607 additionsIndex = mgr.indexOf(queryParts[1]); 608 if (additionsIndex != -1 && queryParts[0].equals("after")) additionsIndex++; 610 } 611 } 612 613 return additionsIndex; 614 } 615 616 621 public IEvaluationContext getCurrentState() { 622 return evaluationService.getCurrentState(); 623 } 624 625 631 public void registerVisibleWhen(final IContributionItem item, 632 final Expression visibleWhen, final Expression restriction, 633 String identifierID) { 634 if (item == null) { 635 throw new IllegalArgumentException ("item cannot be null"); } 637 if (visibleWhen == null) { 638 throw new IllegalArgumentException ( 639 "visibleWhen expression cannot be null"); } 641 if (evaluationsByItem.get(item) != null) { 642 final String id = item.getId(); 643 WorkbenchPlugin.log("item is already registered: " + (id == null ? "no id" : id)); return; 646 } 647 IIdentifier identifier = null; 648 if (identifierID != null) { 649 identifier = PlatformUI.getWorkbench().getActivitySupport() 650 .getActivityManager().getIdentifier(identifierID); 651 } 652 ContributionItemUpdater listener = new ContributionItemUpdater(item, 653 identifier); 654 655 if (visibleWhen != AlwaysEnabledExpression.INSTANCE) { 656 IEvaluationReference ref = evaluationService.addEvaluationListener( 657 visibleWhen, listener, PROP_VISIBLE, restriction); 658 evaluationsByItem.put(item, ref); 659 } 660 activityListenersByItem.put(item, listener); 661 } 662 663 668 public void unregisterVisibleWhen(IContributionItem item) { 669 ContributionItemUpdater identifierListener = (ContributionItemUpdater) activityListenersByItem 670 .get(item); 671 if (identifierListener != null) { 672 identifierListener.dispose(); 673 } 674 675 IEvaluationReference ref = (IEvaluationReference) evaluationsByItem 676 .remove(item); 677 if (ref == null) { 678 return; 679 } 680 681 evaluationService.removeEvaluationListener(ref); 682 } 683 684 689 public void releaseContributions(ContributionManager mgr) { 690 List contributions = (List ) contributionManagerTracker.remove(mgr); 691 if (contributions == null) { 692 return; 693 } 694 695 if (mgr instanceof IMenuManager) { 696 IMenuManager m = (IMenuManager) mgr; 697 if (m.getRemoveAllWhenShown()) { 698 m.removeMenuListener(getMenuTrackerListener()); 699 } 700 } 701 702 Iterator i = contributions.iterator(); 703 while (i.hasNext()) { 704 final ContributionRoot items = (ContributionRoot) i.next(); 705 Iterator j = items.getItems().iterator(); 706 while (j.hasNext()) { 707 IContributionItem item = (IContributionItem) j.next(); 708 releaseItem(item); 709 } 710 releaseCache(items); 711 } 712 contributions.clear(); 713 } 714 715 718 private void releaseItem(IContributionItem item) { 719 unregisterVisibleWhen(item); 720 if (item instanceof ContributionManager) { 721 releaseContributions((ContributionManager) item); 722 } else if (item instanceof IToolBarContributionItem) { 723 IToolBarContributionItem tbci = (IToolBarContributionItem) item; 724 releaseContributions((ContributionManager) tbci.getToolBarManager()); 725 } 726 } 727 } 728 | Popular Tags |