1 12 package org.eclipse.ui.internal; 13 14 import java.util.ArrayList ; 15 import java.util.Collections ; 16 import java.util.HashMap ; 17 import java.util.Iterator ; 18 import java.util.Map ; 19 import java.util.Set ; 20 21 import org.eclipse.core.runtime.IConfigurationElement; 22 import org.eclipse.core.runtime.IExtensionDelta; 23 import org.eclipse.core.runtime.IExtensionPoint; 24 import org.eclipse.core.runtime.IRegistryChangeEvent; 25 import org.eclipse.core.runtime.IRegistryChangeListener; 26 import org.eclipse.core.runtime.Platform; 27 import org.eclipse.jface.action.ContributionManager; 28 import org.eclipse.jface.action.IContributionItem; 29 import org.eclipse.jface.action.IMenuListener2; 30 import org.eclipse.jface.action.IMenuManager; 31 import org.eclipse.jface.action.MenuManager; 32 import org.eclipse.jface.action.Separator; 33 import org.eclipse.jface.action.SubMenuManager; 34 import org.eclipse.jface.viewers.ISelection; 35 import org.eclipse.jface.viewers.ISelectionChangedListener; 36 import org.eclipse.jface.viewers.ISelectionProvider; 37 import org.eclipse.jface.viewers.StructuredSelection; 38 import org.eclipse.swt.widgets.Display; 39 import org.eclipse.ui.IEditorPart; 40 import org.eclipse.ui.IWorkbench; 41 import org.eclipse.ui.IWorkbenchActionConstants; 42 import org.eclipse.ui.IWorkbenchPart; 43 import org.eclipse.ui.IWorkbenchPartSite; 44 import org.eclipse.ui.internal.menus.WindowMenuService; 45 import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants; 46 import org.eclipse.ui.menus.IMenuService; 47 import org.eclipse.ui.menus.MenuUtil; 48 49 52 public class PopupMenuExtender implements IMenuListener2, 53 IRegistryChangeListener { 54 55 59 private static final int STATIC_ACTION_READ = 1; 60 61 65 private static final int INCLUDE_EDITOR_INPUT = 1 << 1; 66 67 private final MenuManager menu; 68 69 private SubMenuManager menuWrapper; 70 71 private final ISelectionProvider selProvider; 72 73 private final IWorkbenchPart part; 74 75 private Map staticActionBuilders = null; 76 77 81 private int bitSet = 0; 82 83 private ArrayList contributionCache = new ArrayList (); 84 85 97 public PopupMenuExtender(String id, MenuManager menu, 98 ISelectionProvider prov, IWorkbenchPart part) { 99 this(id, menu, prov, part, true); 100 } 101 102 117 public PopupMenuExtender(final String id, final MenuManager menu, 118 final ISelectionProvider prov, final IWorkbenchPart part, 119 final boolean includeEditorInput) { 120 super(); 121 this.menu = menu; 122 this.selProvider = prov; 123 this.part = part; 124 if (includeEditorInput) { 125 bitSet |= INCLUDE_EDITOR_INPUT; 126 } 127 menu.addMenuListener(this); 128 if (!menu.getRemoveAllWhenShown()) { 129 menuWrapper = new SubMenuManager(menu); 130 menuWrapper.setVisible(true); 131 } 132 readStaticActionsFor(id); 133 134 Platform.getExtensionRegistry().addRegistryChangeListener(this); 135 } 136 137 143 public Set getMenuIds() { 144 if (staticActionBuilders == null) { 145 return Collections.EMPTY_SET; 146 } 147 148 return staticActionBuilders.keySet(); 149 } 150 151 171 public final void addMenuId(final String menuId) { 172 bitSet &= ~STATIC_ACTION_READ; 173 readStaticActionsFor(menuId); 174 } 175 176 194 public final boolean matches(final MenuManager menuManager, 195 final ISelectionProvider selectionProvider, 196 final IWorkbenchPart part) { 197 return (this.menu == menuManager) 198 && (this.selProvider == selectionProvider) 199 && (this.part == part); 200 } 201 202 205 private void addEditorActions(IMenuManager mgr) { 206 ISelectionProvider activeEditor = new ISelectionProvider() { 207 208 211 public void addSelectionChangedListener( 212 ISelectionChangedListener listener) { 213 throw new UnsupportedOperationException ( 214 "This ISelectionProvider is static, and cannot be modified."); } 216 217 220 public ISelection getSelection() { 221 if (part instanceof IEditorPart) { 222 final IEditorPart editorPart = (IEditorPart) part; 223 return new StructuredSelection(new Object [] { editorPart 224 .getEditorInput() }); 225 } 226 227 return new StructuredSelection(new Object [0]); 228 } 229 230 233 public void removeSelectionChangedListener( 234 ISelectionChangedListener listener) { 235 throw new UnsupportedOperationException ( 236 "This ISelectionProvider is static, and cannot be modified."); } 238 239 242 public void setSelection(ISelection selection) { 243 throw new UnsupportedOperationException ( 244 "This ISelectionProvider is static, and cannot be modified."); } 246 }; 247 248 if (ObjectActionContributorManager.getManager() 249 .contributeObjectActions(part, mgr, activeEditor)) { 250 mgr.add(new Separator()); 251 } 252 } 253 254 258 private void addObjectActions(IMenuManager mgr) { 259 if (selProvider != null) { 260 if (ObjectActionContributorManager.getManager() 261 .contributeObjectActions(part, mgr, selProvider)) { 262 mgr.add(new Separator()); 263 } 264 } 265 } 266 267 270 private final void clearStaticActions() { 271 bitSet &= ~STATIC_ACTION_READ; 272 if (staticActionBuilders != null) { 273 final Iterator staticActionBuilderItr = staticActionBuilders 274 .values().iterator(); 275 while (staticActionBuilderItr.hasNext()) { 276 final Object staticActionBuilder = staticActionBuilderItr 277 .next(); 278 if (staticActionBuilder instanceof ViewerActionBuilder) { 279 ((ViewerActionBuilder) staticActionBuilder).dispose(); 280 } 281 } 282 } 283 } 284 285 288 private void addStaticActions(IMenuManager mgr) { 289 if (staticActionBuilders != null) { 290 final Iterator staticActionBuilderItr = staticActionBuilders 291 .values().iterator(); 292 while (staticActionBuilderItr.hasNext()) { 293 final ViewerActionBuilder staticActionBuilder = (ViewerActionBuilder) staticActionBuilderItr 294 .next(); 295 staticActionBuilder.contribute(mgr, null, true); 296 } 297 } 298 } 299 300 303 public void menuAboutToShow(IMenuManager mgr) { 304 IMenuManager originalManager = mgr; 305 306 final IWorkbenchPartSite site = part.getSite(); 308 if (site != null) { 309 final IWorkbench workbench = site.getWorkbenchWindow() 310 .getWorkbench(); 311 if (workbench instanceof Workbench) { 312 final Workbench realWorkbench = (Workbench) workbench; 313 ISelection input = null; 314 if ((bitSet & INCLUDE_EDITOR_INPUT) != 0) { 315 if (part instanceof IEditorPart) { 316 final IEditorPart editorPart = (IEditorPart) part; 317 input = new StructuredSelection( 318 new Object [] { editorPart.getEditorInput() }); 319 } 320 } 321 ISelection s = (selProvider == null ? null : selProvider 322 .getSelection()); 323 realWorkbench.addShowingMenus(getMenuIds(), s, input); 324 } 325 } 326 327 readStaticActions(); 328 testForAdditions(); 329 if (menuWrapper != null) { 330 mgr = menuWrapper; 331 menuWrapper.removeAll(); 332 } 333 addMenuContributions(originalManager); 334 if ((bitSet & INCLUDE_EDITOR_INPUT) != 0) { 335 addEditorActions(mgr); 336 } 337 addObjectActions(mgr); 338 addStaticActions(mgr); 339 cleanUpContributionCache(); 340 } 341 342 private boolean contributionsPopulated = false; 343 344 private void addMenuContributions(IMenuManager mgr) { 345 final IMenuService menuService = (IMenuService) part.getSite() 346 .getService(IMenuService.class); 347 if (menuService == null) { 348 return; 349 } 350 if ((mgr.getRemoveAllWhenShown() || !contributionsPopulated) 351 && mgr instanceof ContributionManager) { 352 ContributionManager manager = (ContributionManager) mgr; 353 contributionsPopulated = true; 354 menuService 355 .populateContributionManager(manager, MenuUtil.ANY_POPUP); 356 Iterator i = getMenuIds().iterator(); 357 WindowMenuService realService = (WindowMenuService) menuService; 358 while (i.hasNext()) { 359 String id = "popup:" + i.next(); realService.populateContributionManager(manager, id, false); 361 } 362 } 363 } 364 365 368 public final void menuAboutToHide(final IMenuManager mgr) { 369 gatherContributions(mgr); 370 final IWorkbenchPartSite site = part.getSite(); 372 if (site != null) { 373 final IWorkbench workbench = site.getWorkbenchWindow().getWorkbench(); 374 if (workbench instanceof Workbench) { 375 workbench.getDisplay().asyncExec(new Runnable () { 380 public void run() { 381 final Workbench realWorkbench = (Workbench) workbench; 382 realWorkbench.removeShowingMenus(getMenuIds(), null, null); 383 } 384 }); 385 } 386 } 387 } 388 389 390 393 private void gatherContributions(final IMenuManager mgr) { 394 final IContributionItem[] items = mgr.getItems(); 395 for (int i = 0; i < items.length; i++) { 396 if (items[i] instanceof PluginActionContributionItem) { 397 contributionCache.add(items[i]); 398 } else if (items[i] instanceof IMenuManager) { 399 gatherContributions(((IMenuManager)items[i])); 400 } 401 } 402 } 403 404 private void cleanUpContributionCache() { 405 PluginActionContributionItem[] items = (PluginActionContributionItem[]) contributionCache 406 .toArray(new PluginActionContributionItem[contributionCache.size()]); 407 contributionCache.clear(); 408 for (int i = 0; i < items.length; i++) { 409 items[i].dispose(); 410 } 411 } 412 413 416 private final void readStaticActions() { 417 if (staticActionBuilders != null) { 418 final Iterator menuIdItr = staticActionBuilders.keySet().iterator(); 419 while (menuIdItr.hasNext()) { 420 final String menuId = (String ) menuIdItr.next(); 421 readStaticActionsFor(menuId); 422 } 423 } 424 } 425 426 429 private void readStaticActionsFor(final String menuId) { 430 if ((bitSet & STATIC_ACTION_READ) != 0) { 431 return; 432 } 433 434 bitSet |= STATIC_ACTION_READ; 435 436 if ((menuId == null) || (menuId.length() < 1)) { 439 return; 440 } 441 442 if (staticActionBuilders == null) { 443 staticActionBuilders = new HashMap (); 444 } 445 446 Object object = staticActionBuilders.get(menuId); 447 if (!(object instanceof ViewerActionBuilder)) { 448 object = new ViewerActionBuilder(); 449 staticActionBuilders.put(menuId, object); 450 } 451 final ViewerActionBuilder staticActionBuilder = (ViewerActionBuilder) object; 452 staticActionBuilder.readViewerContributions(menuId, selProvider, part); 453 } 454 455 458 private void testForAdditions() { 459 IContributionItem item = menu 460 .find(IWorkbenchActionConstants.MB_ADDITIONS); 461 if (item == null) { 462 WorkbenchPlugin 463 .log("Context menu missing standard group 'org.eclipse.ui.IWorkbenchActionConstants.MB_ADDITIONS'. (menu ids = " + getMenuIds().toString() + ") part id = " + (part == null ? "???" : part.getSite().getId()) + ")"); } 468 } 469 470 474 public void dispose() { 475 clearStaticActions(); 476 final IMenuService menuService = (IMenuService) part.getSite() 477 .getService(IMenuService.class); 478 if (menuService != null) { 479 menuService.releaseContributions(menu); 480 } 481 Platform.getExtensionRegistry().removeRegistryChangeListener(this); 482 menu.removeMenuListener(this); 483 } 484 485 490 public void registryChanged(final IRegistryChangeEvent event) { 491 Display display = Display.getDefault(); 492 if (part != null) { 493 display = part.getSite().getPage().getWorkbenchWindow().getWorkbench().getDisplay(); 494 } 495 IExtensionDelta [] deltas = event.getExtensionDeltas(); 497 for (int i = 0; i < deltas.length; i++) { 498 IExtensionDelta delta = deltas[i]; 499 IExtensionPoint extensionPoint = delta.getExtensionPoint(); 500 if (extensionPoint.getNamespace().equals( 501 WorkbenchPlugin.PI_WORKBENCH) 502 && extensionPoint.getSimpleIdentifier().equals( 503 IWorkbenchRegistryConstants.PL_POPUP_MENU)) { 504 505 boolean clearPopups = false; 506 IConfigurationElement [] elements = delta.getExtension().getConfigurationElements(); 507 for (int j = 0; j < elements.length; j++) { 508 IConfigurationElement element = elements[j]; 509 if (element.getName().equals(IWorkbenchRegistryConstants.TAG_VIEWER_CONTRIBUTION)) { 510 clearPopups = true; 511 break; 512 } 513 } 514 515 if (clearPopups) { 516 display.syncExec(new Runnable () { 517 public void run() { 518 clearStaticActions(); 519 } 520 }); 521 } 522 } 523 } 524 } 525 526 public MenuManager getManager() { 527 return menu; 528 } 529 } 530 | Popular Tags |