1 /******************************************************************************* 2 * Copyright (c) 2000, 2019 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 * Christian Janz - <christian.janz@gmail.com> Fix for Bug 385592 14 * Marc-Andre Laperle (Ericsson) - Fix for Bug 413590 15 * Lars Vogel <Lars.Vogel@vogella.com> - Bug 431340, 431348, 426535, 433234, 431868, 472654 16 * Cornel Izbasa <cizbasa@info.uvt.ro> - Bug 442214 17 * Andrey Loskutov <loskutov@gmx.de> - Bug 411639, 372799, 466230 18 * Dirk Fauth <dirk.fauth@googlemail.com> - Bug 473063 19 * Stefan Prieschl <stefan.prieschl@gmail.com> - Bug 374132 20 * Paul Pazderski <paul-eclipse@ppazderski.de> - Bug 549361 21 *******************************************************************************/ 22 23 package org.eclipse.ui.internal; 24 25 import java.io.File; 26 import java.io.IOException; 27 import java.io.StringReader; 28 import java.io.StringWriter; 29 import java.net.MalformedURLException; 30 import java.net.URI; 31 import java.net.URISyntaxException; 32 import java.text.MessageFormat; 33 import java.util.ArrayList; 34 import java.util.Arrays; 35 import java.util.Collection; 36 import java.util.Collections; 37 import java.util.HashMap; 38 import java.util.HashSet; 39 import java.util.Iterator; 40 import java.util.LinkedHashMap; 41 import java.util.LinkedHashSet; 42 import java.util.List; 43 import java.util.ListIterator; 44 import java.util.Map; 45 import java.util.Objects; 46 import java.util.Set; 47 import java.util.WeakHashMap; 48 import javax.annotation.PostConstruct; 49 import javax.annotation.PreDestroy; 50 import javax.inject.Inject; 51 import org.eclipse.core.runtime.Adapters; 52 import org.eclipse.core.runtime.Assert; 53 import org.eclipse.core.runtime.CoreException; 54 import org.eclipse.core.runtime.IAdaptable; 55 import org.eclipse.core.runtime.IConfigurationElement; 56 import org.eclipse.core.runtime.IPath; 57 import org.eclipse.core.runtime.IStatus; 58 import org.eclipse.core.runtime.ListenerList; 59 import org.eclipse.core.runtime.SafeRunner; 60 import org.eclipse.core.runtime.Status; 61 import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker; 62 import org.eclipse.e4.core.contexts.ContextInjectionFactory; 63 import org.eclipse.e4.core.contexts.IEclipseContext; 64 import org.eclipse.e4.core.di.annotations.Optional; 65 import org.eclipse.e4.core.services.events.IEventBroker; 66 import org.eclipse.e4.ui.di.UIEventTopic; 67 import org.eclipse.e4.ui.internal.workbench.ModelServiceImpl; 68 import org.eclipse.e4.ui.internal.workbench.PartServiceImpl; 69 import org.eclipse.e4.ui.model.application.MApplication; 70 import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor; 71 import org.eclipse.e4.ui.model.application.ui.MElementContainer; 72 import org.eclipse.e4.ui.model.application.ui.MGenericStack; 73 import org.eclipse.e4.ui.model.application.ui.MUIElement; 74 import org.eclipse.e4.ui.model.application.ui.advanced.MArea; 75 import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective; 76 import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack; 77 import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder; 78 import org.eclipse.e4.ui.model.application.ui.basic.MPart; 79 import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer; 80 import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement; 81 import org.eclipse.e4.ui.model.application.ui.basic.MPartStack; 82 import org.eclipse.e4.ui.model.application.ui.basic.MStackElement; 83 import org.eclipse.e4.ui.model.application.ui.basic.MTrimElement; 84 import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow; 85 import org.eclipse.e4.ui.model.application.ui.basic.MWindow; 86 import org.eclipse.e4.ui.model.application.ui.basic.MWindowElement; 87 import org.eclipse.e4.ui.model.application.ui.menu.MToolControl; 88 import org.eclipse.e4.ui.workbench.IPresentationEngine; 89 import org.eclipse.e4.ui.workbench.UIEvents; 90 import org.eclipse.e4.ui.workbench.UIEvents.EventTags; 91 import org.eclipse.e4.ui.workbench.modeling.EModelService; 92 import org.eclipse.e4.ui.workbench.modeling.EPartService; 93 import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState; 94 import org.eclipse.emf.ecore.EObject; 95 import org.eclipse.emf.ecore.util.EcoreUtil; 96 import org.eclipse.jface.dialogs.DialogSettings; 97 import org.eclipse.jface.dialogs.IDialogSettings; 98 import org.eclipse.jface.dialogs.IPageChangeProvider; 99 import org.eclipse.jface.dialogs.IPageChangedListener; 100 import org.eclipse.jface.internal.provisional.action.ICoolBarManager2; 101 import org.eclipse.jface.operation.IRunnableContext; 102 import org.eclipse.jface.preference.IPreferenceStore; 103 import org.eclipse.jface.resource.ImageDescriptor; 104 import org.eclipse.jface.util.IPropertyChangeListener; 105 import org.eclipse.jface.util.PropertyChangeEvent; 106 import org.eclipse.jface.util.SafeRunnable; 107 import org.eclipse.jface.viewers.ISelection; 108 import org.eclipse.jface.viewers.ISelectionProvider; 109 import org.eclipse.jface.window.Window; 110 import org.eclipse.osgi.util.NLS; 111 import org.eclipse.swt.custom.BusyIndicator; 112 import org.eclipse.swt.dnd.DND; 113 import org.eclipse.swt.dnd.DropTarget; 114 import org.eclipse.swt.dnd.DropTargetListener; 115 import org.eclipse.swt.program.Program; 116 import org.eclipse.swt.widgets.Composite; 117 import org.eclipse.swt.widgets.Control; 118 import org.eclipse.swt.widgets.Shell; 119 import org.eclipse.ui.IActionBars; 120 import org.eclipse.ui.IEditorDescriptor; 121 import org.eclipse.ui.IEditorInput; 122 import org.eclipse.ui.IEditorLauncher; 123 import org.eclipse.ui.IEditorMatchingStrategy; 124 import org.eclipse.ui.IEditorPart; 125 import org.eclipse.ui.IEditorReference; 126 import org.eclipse.ui.IEditorRegistry; 127 import org.eclipse.ui.IMemento; 128 import org.eclipse.ui.INavigationHistory; 129 import org.eclipse.ui.IPageLayout; 130 import org.eclipse.ui.IPartListener; 131 import org.eclipse.ui.IPartListener2; 132 import org.eclipse.ui.IPathEditorInput; 133 import org.eclipse.ui.IPersistableEditor; 134 import org.eclipse.ui.IPersistableElement; 135 import org.eclipse.ui.IPerspectiveDescriptor; 136 import org.eclipse.ui.IPerspectiveFactory; 137 import org.eclipse.ui.IPerspectiveRegistry; 138 import org.eclipse.ui.IReusableEditor; 139 import org.eclipse.ui.ISaveablePart; 140 import org.eclipse.ui.ISaveablePart2; 141 import org.eclipse.ui.ISaveablesLifecycleListener; 142 import org.eclipse.ui.ISaveablesSource; 143 import org.eclipse.ui.ISelectionListener; 144 import org.eclipse.ui.ISelectionService; 145 import org.eclipse.ui.IShowEditorInput; 146 import org.eclipse.ui.ISources; 147 import org.eclipse.ui.IViewPart; 148 import org.eclipse.ui.IViewReference; 149 import org.eclipse.ui.IWorkbenchPage; 150 import org.eclipse.ui.IWorkbenchPart; 151 import org.eclipse.ui.IWorkbenchPartReference; 152 import org.eclipse.ui.IWorkbenchPartSite; 153 import org.eclipse.ui.IWorkbenchPreferenceConstants; 154 import org.eclipse.ui.IWorkbenchWindow; 155 import org.eclipse.ui.IWorkingSet; 156 import org.eclipse.ui.IWorkingSetManager; 157 import org.eclipse.ui.MultiPartInitException; 158 import org.eclipse.ui.PartInitException; 159 import org.eclipse.ui.PlatformUI; 160 import org.eclipse.ui.Saveable; 161 import org.eclipse.ui.WorkbenchException; 162 import org.eclipse.ui.XMLMemento; 163 import org.eclipse.ui.contexts.IContextService; 164 import org.eclipse.ui.dialogs.EditorSelectionDialog; 165 import org.eclipse.ui.internal.dialogs.cpd.CustomizePerspectiveDialog; 166 import org.eclipse.ui.internal.e4.compatibility.CompatibilityEditor; 167 import org.eclipse.ui.internal.e4.compatibility.CompatibilityPart; 168 import org.eclipse.ui.internal.e4.compatibility.CompatibilityView; 169 import org.eclipse.ui.internal.e4.compatibility.ModeledPageLayout; 170 import org.eclipse.ui.internal.e4.compatibility.SelectionService; 171 import org.eclipse.ui.internal.menus.MenuHelper; 172 import org.eclipse.ui.internal.misc.ExternalEditor; 173 import org.eclipse.ui.internal.misc.StatusUtil; 174 import org.eclipse.ui.internal.misc.UIListenerLogging; 175 import org.eclipse.ui.internal.progress.ProgressManagerUtil; 176 import org.eclipse.ui.internal.registry.ActionSetRegistry; 177 import org.eclipse.ui.internal.registry.EditorDescriptor; 178 import org.eclipse.ui.internal.registry.IActionSetDescriptor; 179 import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants; 180 import org.eclipse.ui.internal.registry.PerspectiveDescriptor; 181 import org.eclipse.ui.internal.registry.PerspectiveRegistry; 182 import org.eclipse.ui.internal.registry.UIExtensionTracker; 183 import org.eclipse.ui.internal.registry.ViewDescriptor; 184 import org.eclipse.ui.internal.tweaklets.TabBehaviour; 185 import org.eclipse.ui.internal.tweaklets.Tweaklets; 186 import org.eclipse.ui.internal.util.PrefUtil; 187 import org.eclipse.ui.model.IWorkbenchAdapter; 188 import org.eclipse.ui.part.IShowInSource; 189 import org.eclipse.ui.part.ShowInContext; 190 import org.eclipse.ui.statushandlers.StatusManager; 191 import org.eclipse.ui.views.IStickyViewDescriptor; 192 import org.eclipse.ui.views.IViewDescriptor; 193 import org.osgi.service.event.Event; 194 import org.osgi.service.event.EventHandler; 195 196 /** 197 * A collection of views and editors in a workbench. 198 */ 199 public class WorkbenchPage implements IWorkbenchPage { 200 201 private static final String ATT_AGGREGATE_WORKING_SET_ID = "aggregateWorkingSetId"; //$NON-NLS-1$ 202 203 private static final int WINDOW_SCOPE = EModelService.OUTSIDE_PERSPECTIVE | EModelService.IN_ANY_PERSPECTIVE 204 | EModelService.IN_SHARED_AREA; 205 206 class E4PartListener implements org.eclipse.e4.ui.workbench.modeling.IPartListener { 207 208 @Override partActivated(MPart part)209 public void partActivated(MPart part) { 210 // update the workbench window's current selection with the active 211 // part's selection 212 IWorkbenchPart workbenchPart = getWorkbenchPart(part); 213 selectionService.updateSelection(workbenchPart); 214 215 updateActivations(part); 216 firePartActivated(part); 217 selectionService.notifyListeners(workbenchPart); 218 } 219 220 @Override partBroughtToTop(MPart part)221 public void partBroughtToTop(MPart part) { 222 updateBroughtToTop(part); 223 firePartBroughtToTop(part); 224 } 225 226 @Override partDeactivated(MPart part)227 public void partDeactivated(MPart part) { 228 firePartDeactivated(part); 229 230 Object client = part.getObject(); 231 if (client instanceof CompatibilityPart) { 232 IWorkbenchPart workbenchPart = getWrappedPart((CompatibilityPart) client); 233 if (workbenchPart == null) { 234 return; 235 } 236 IWorkbenchPartSite site = workbenchPart.getSite(); 237 // if it's an editor, we only want to disable the actions 238 ((PartSite) site).deactivateActionBars(site instanceof ViewSite); 239 } 240 241 WorkbenchWindow wwindow = (WorkbenchWindow) getWorkbenchWindow(); 242 if (!wwindow.isClosing()) { 243 wwindow.getStatusLineManager().update(false); 244 } 245 } 246 247 @Override partHidden(MPart part)248 public void partHidden(MPart part) { 249 firePartHidden(part); 250 } 251 252 @Override partVisible(MPart part)253 public void partVisible(MPart part) { 254 firePartVisible(part); 255 } 256 } 257 258 ArrayList<MPart> activationList = new ArrayList<>(); 259 260 /** 261 * Cached perspective stack for this workbench page. 262 */ 263 private MPerspectiveStack _perspectiveStack; 264 265 /** Ids of parts used as Show In targets, maintained in MRU order */ 266 private List<String> mruShowInPartIds = new ArrayList<>(); 267 268 /** 269 * Deactivate the last editor's action bars if another type of editor has // * 270 * been activated. 271 * 272 * @param part the part that is being activated 273 */ deactivateLastEditor(MPart part)274 private void deactivateLastEditor(MPart part) { 275 Object client = part.getObject(); 276 // we only care if the currently activated part is an editor 277 if (client instanceof CompatibilityEditor) { 278 IWorkbenchPart activePart = getWrappedPart((CompatibilityEditor) client); 279 if (activePart == null) { 280 return; 281 } 282 String activeId = activePart.getSite().getId(); 283 284 // find another editor that was last activated 285 for (MPart previouslyActive : activationList) { 286 if (previouslyActive != part) { 287 Object object = previouslyActive.getObject(); 288 if (object instanceof CompatibilityEditor) { 289 IWorkbenchPart workbenchPart = getWrappedPart((CompatibilityEditor) object); 290 if (workbenchPart == null) { 291 continue; 292 } 293 EditorSite site = (EditorSite) workbenchPart.getSite(); 294 String lastId = site.getId(); 295 296 // if not the same, hide the other editor's action bars 297 if (lastId != null && !lastId.equals(activeId)) { 298 site.deactivateActionBars(true); 299 } 300 break; 301 } 302 } 303 } 304 } 305 } 306 updateActivations(MPart part)307 private void updateActivations(MPart part) { 308 if (activationList.size() > 1) { 309 deactivateLastEditor(part); 310 } 311 312 activationList.remove(part); 313 activationList.add(0, part); 314 updateActivePartSources(part); 315 updateActiveEditorSources(part); 316 317 Object client = part.getObject(); 318 if (client instanceof CompatibilityPart) { 319 IWorkbenchPart workbenchPart = getWrappedPart((CompatibilityPart) client); 320 if (workbenchPart != null) { 321 PartSite site = (PartSite) workbenchPart.getSite(); 322 site.activateActionBars(true); 323 324 IActionBars actionBars = site.getActionBars(); 325 if (actionBars instanceof EditorActionBars) { 326 ((EditorActionBars) actionBars).partChanged(workbenchPart); 327 } 328 } 329 } 330 331 ((WorkbenchWindow) getWorkbenchWindow()).getStatusLineManager().update(false); 332 333 IWorkbenchPart workbenchPart = getWorkbenchPart(part); 334 actionSwitcher.updateActivePart(workbenchPart); 335 } 336 updateActivePartSources(MPart part)337 private void updateActivePartSources(MPart part) { 338 IWorkbenchPart workbenchPart = getWorkbenchPart(part); 339 IContextService cs = legacyWindow.getService(IContextService.class); 340 try { 341 cs.deferUpdates(true); 342 if (workbenchPart == null) { 343 window.getContext().set(ISources.ACTIVE_PART_NAME, null); 344 window.getContext().set(ISources.ACTIVE_PART_ID_NAME, null); 345 window.getContext().set(ISources.ACTIVE_SITE_NAME, null); 346 } else { 347 window.getContext().set(ISources.ACTIVE_PART_NAME, workbenchPart); 348 window.getContext().set(ISources.ACTIVE_PART_ID_NAME, workbenchPart.getSite().getId()); 349 window.getContext().set(ISources.ACTIVE_SITE_NAME, workbenchPart.getSite()); 350 } 351 } finally { 352 cs.deferUpdates(false); 353 } 354 } 355 updateActionSets(Perspective oldPersp, Perspective newPersp)356 private void updateActionSets(Perspective oldPersp, Perspective newPersp) { 357 // Update action sets 358 359 IContextService service = legacyWindow.getService(IContextService.class); 360 try { 361 service.deferUpdates(true); 362 if (newPersp != null) { 363 for (IActionSetDescriptor descriptor : newPersp.getAlwaysOnActionSets()) { 364 actionSets.showAction(descriptor); 365 } 366 367 for (IActionSetDescriptor descriptor : newPersp.getAlwaysOffActionSets()) { 368 actionSets.maskAction(descriptor); 369 } 370 } 371 372 if (oldPersp != null) { 373 for (IActionSetDescriptor descriptor : oldPersp.getAlwaysOnActionSets()) { 374 actionSets.hideAction(descriptor); 375 } 376 377 for (IActionSetDescriptor descriptor : oldPersp.getAlwaysOffActionSets()) { 378 actionSets.unmaskAction(descriptor); 379 } 380 } 381 } finally { 382 service.deferUpdates(false); 383 } 384 } 385 getWorkbenchPart(MPart part)386 private IWorkbenchPart getWorkbenchPart(MPart part) { 387 if (part != null) { 388 Object clientObject = part.getObject(); 389 if (clientObject instanceof CompatibilityPart) { 390 return ((CompatibilityPart) clientObject).getPart(); 391 } else if (clientObject != null) { 392 if (part.getTransientData().get(E4PartWrapper.E4_WRAPPER_KEY) instanceof E4PartWrapper) { 393 return (IWorkbenchPart) part.getTransientData().get(E4PartWrapper.E4_WRAPPER_KEY); 394 } 395 396 ViewReference viewReference = getViewReference(part); 397 if (viewReference != null) { 398 E4PartWrapper legacyPart = E4PartWrapper.getE4PartWrapper(part); 399 try { 400 viewReference.initialize(legacyPart); 401 } catch (PartInitException e) { 402 WorkbenchPlugin.log(e); 403 } 404 part.getTransientData().put(E4PartWrapper.E4_WRAPPER_KEY, legacyPart); 405 return legacyPart; 406 } 407 } 408 } 409 return null; 410 } 411 updateActiveEditorSources(MPart part)412 private void updateActiveEditorSources(MPart part) { 413 IEditorPart editor = getEditor(part); 414 window.getContext().set(ISources.ACTIVE_EDITOR_ID_NAME, editor == null ? null : editor.getSite().getId()); 415 window.getContext().set(ISources.ACTIVE_EDITOR_NAME, editor); 416 window.getContext().set(ISources.ACTIVE_EDITOR_INPUT_NAME, editor == null ? null : editor.getEditorInput()); 417 418 if (editor != null) { 419 navigationHistory.markEditor(editor); 420 } 421 actionSwitcher.updateTopEditor(editor); 422 } 423 updateShowInSources(MPart part)424 public void updateShowInSources(MPart part) { 425 426 IWorkbenchPart workbenchPart = getWorkbenchPart(part); 427 ShowInContext context = getContext(workbenchPart); 428 if (context != null) { 429 window.getContext().set(ISources.SHOW_IN_INPUT, context.getInput()); 430 window.getContext().set(ISources.SHOW_IN_SELECTION, context.getSelection()); 431 } 432 } 433 getShowInSource(IWorkbenchPart sourcePart)434 private IShowInSource getShowInSource(IWorkbenchPart sourcePart) { 435 return Adapters.adapt(sourcePart, IShowInSource.class); 436 } 437 getContext(IWorkbenchPart sourcePart)438 private ShowInContext getContext(IWorkbenchPart sourcePart) { 439 IShowInSource source = getShowInSource(sourcePart); 440 if (source != null) { 441 ShowInContext context = source.getShowInContext(); 442 if (context != null) { 443 return context; 444 } 445 } else if (sourcePart instanceof IEditorPart) { 446 Object input = ((IEditorPart) sourcePart).getEditorInput(); 447 ISelectionProvider sp = sourcePart.getSite().getSelectionProvider(); 448 ISelection sel = sp == null ? null : sp.getSelection(); 449 return new ShowInContext(input, sel); 450 } 451 return null; 452 } 453 getEditor(MPart part)454 private IEditorPart getEditor(MPart part) { 455 if (part != null) { 456 Object clientObject = part.getObject(); 457 if (clientObject instanceof CompatibilityEditor) { 458 return ((CompatibilityEditor) clientObject).getEditor(); 459 } 460 } 461 return getActiveEditor(); 462 } 463 updateBroughtToTop(MPart part)464 private void updateBroughtToTop(MPart part) { 465 updateActiveEditorSources(part); 466 IWorkbenchPart workbenchPart = getWorkbenchPart(part); 467 if (workbenchPart instanceof IEditorPart) { 468 navigationHistory.markEditor((IEditorPart) workbenchPart); 469 } 470 471 MElementContainer<?> parent = part.getParent(); 472 if (parent == null) { 473 MPlaceholder placeholder = part.getCurSharedRef(); 474 if (placeholder == null) { 475 return; 476 } 477 478 parent = placeholder.getParent(); 479 } 480 481 if (parent instanceof MPartStack) { 482 int newIndex = lastIndexOfContainer(parent); 483 // New index can be -1 if there is no last index 484 if (newIndex >= 0 && part == activationList.get(newIndex)) { 485 return; 486 } 487 activationList.remove(part); 488 if (newIndex >= 0 && newIndex < activationList.size() - 1) { 489 activationList.add(newIndex, part); 490 } else { 491 activationList.add(part); 492 } 493 } 494 } 495 lastIndexOfContainer(MElementContainer<?> parent)496 private int lastIndexOfContainer(MElementContainer<?> parent) { 497 for (int i = 0; i < activationList.size(); i++) { 498 MPart mPart = activationList.get(i); 499 MElementContainer<MUIElement> container = mPart.getParent(); 500 if (container == parent) { 501 return i; 502 } else if (container == null) { 503 MPlaceholder placeholder = mPart.getCurSharedRef(); 504 if (placeholder != null && placeholder.getParent() == parent) { 505 return i; 506 } 507 } 508 } 509 return -1; 510 } 511 512 private List<ViewReference> viewReferences = new ArrayList<>(); 513 private List<EditorReference> editorReferences = new ArrayList<>(); 514 515 private List<IPerspectiveDescriptor> sortedPerspectives = new ArrayList<>(); 516 517 private ListenerList<IPartListener> partListenerList = new ListenerList<>(); 518 private ListenerList<IPartListener2> partListener2List = new ListenerList<>(); 519 520 /** 521 * A listener that forwards page change events to our part listeners. 522 */ 523 private IPageChangedListener pageChangedListener = event -> { 524 for (final IPartListener2 listener : partListener2List) { 525 if (listener instanceof IPageChangedListener) { 526 SafeRunner.run(new SafeRunnable() { 527 @Override 528 public void run() throws Exception { 529 ((IPageChangedListener) listener).pageChanged(event); 530 } 531 }); 532 } 533 } 534 }; 535 536 private E4PartListener e4PartListener = new E4PartListener(); 537 538 protected WorkbenchWindow legacyWindow; 539 540 private IAdaptable input; 541 542 private IWorkingSet workingSet; 543 544 private AggregateWorkingSet aggregateWorkingSet; 545 546 private Composite composite; 547 548 private ListenerList<IPropertyChangeListener> propertyChangeListeners = new ListenerList<>(); 549 550 private IActionBars actionBars; 551 552 private ActionSetManager actionSets; 553 554 private NavigationHistory navigationHistory = new NavigationHistory(this); 555 556 /** 557 * If we're in the process of activating a part, this points to the new part. 558 * Otherwise, this is null. 559 */ 560 private IWorkbenchPartReference partBeingActivated = null; 561 562 private IWorkingSet[] workingSets = new IWorkingSet[0]; 563 564 private IPropertyChangeListener workingSetPropertyChangeListener = event -> { 565 String property = event.getProperty(); 566 if (IWorkingSetManager.CHANGE_WORKING_SET_REMOVE.equals(property)) { 567 if (event.getOldValue().equals(workingSet)) { 568 setWorkingSet(null); 569 } 570 571 // room for optimization here 572 List<IWorkingSet> newList = new ArrayList<>(Arrays.asList(workingSets)); 573 if (newList.remove(event.getOldValue())) { 574 setWorkingSets(newList.toArray(new IWorkingSet[newList.size()])); 575 } 576 } 577 }; 578 579 private ActionSwitcher actionSwitcher = new ActionSwitcher(); 580 581 private IExtensionTracker tracker; 582 583 // Deferral count... delays disposing parts and sending certain events if 584 // nonzero 585 private int deferCount = 0; 586 587 private String aggregateWorkingSetId; 588 589 // determines if a prompt is shown when opening large files 590 private long maxFileSize = 0; 591 private boolean checkDocumentSize; 592 593 /** 594 * Manages editor contributions and action set part associations. 595 */ 596 private class ActionSwitcher { 597 private IWorkbenchPart activePart; 598 599 private IEditorPart topEditor; 600 601 private List<IActionSetDescriptor> oldActionSets = new ArrayList<>(); 602 603 /** 604 * Updates the contributions given the new part as the active part. 605 * 606 * @param newPart the new active part, may be <code>null</code> 607 */ updateActivePart(IWorkbenchPart newPart)608 public void updateActivePart(IWorkbenchPart newPart) { 609 if (activePart == newPart) { 610 return; 611 } 612 613 boolean isNewPartAnEditor = newPart instanceof IEditorPart; 614 if (isNewPartAnEditor) { 615 String oldId = null; 616 if (topEditor != null) { 617 oldId = topEditor.getSite().getId(); 618 } 619 String newId = newPart.getSite().getId(); 620 621 // if the active part is an editor and the new editor 622 // is the same kind of editor, then we don't have to do 623 // anything 624 if (activePart == topEditor && newId.equals(oldId)) { 625 activePart = newPart; 626 topEditor = (IEditorPart) newPart; 627 return; 628 } 629 630 // remove the contributions of the old editor 631 // if it is a different kind of editor 632 if (oldId != null && !oldId.equals(newId)) { 633 deactivateContributions(topEditor, true); 634 } 635 636 // if a view was the active part, disable its contributions 637 if (activePart != null && activePart != topEditor) { 638 deactivateContributions(activePart, true); 639 } 640 641 // show (and enable) the contributions of the new editor 642 // if it is a different kind of editor or if the 643 // old active part was a view 644 if (!newId.equals(oldId) || activePart != topEditor) { 645 activateContributions(newPart, true); 646 } 647 648 } else if (newPart == null) { 649 if (activePart != null) { 650 // remove all contributions 651 deactivateContributions(activePart, true); 652 } 653 } else { 654 // new part is a view 655 656 // if old active part is a view, remove all contributions, 657 // but if old part is an editor only disable 658 if (activePart != null) { 659 deactivateContributions(activePart, activePart instanceof IViewPart); 660 } 661 662 activateContributions(newPart, true); 663 } 664 665 List<IActionSetDescriptor> newActionSets = null; 666 if (isNewPartAnEditor || (activePart == topEditor && newPart == null)) { 667 newActionSets = calculateActionSets(newPart, null); 668 } else { 669 newActionSets = calculateActionSets(newPart, topEditor); 670 } 671 672 if (!updateActionSets(newActionSets)) { 673 updateActionBars(); 674 } 675 676 if (isNewPartAnEditor) { 677 topEditor = (IEditorPart) newPart; 678 } else if (activePart == topEditor && newPart == null) { 679 // since we removed all the contributions, we clear the top 680 // editor 681 topEditor = null; 682 } 683 684 activePart = newPart; 685 } 686 687 /** 688 * Updates the contributions given the new part as the topEditor. 689 * 690 * @param newEditor the new top editor, may be <code>null</code> 691 */ updateTopEditor(IEditorPart newEditor)692 public void updateTopEditor(IEditorPart newEditor) { 693 if (topEditor == newEditor) { 694 return; 695 } 696 697 if (activePart == topEditor) { 698 updateActivePart(newEditor); 699 return; 700 } 701 702 String oldId = null; 703 if (topEditor != null) { 704 oldId = topEditor.getSite().getId(); 705 } 706 String newId = null; 707 if (newEditor != null) { 708 newId = newEditor.getSite().getId(); 709 } 710 if (oldId == null ? newId == null : oldId.equals(newId)) { 711 // we don't have to change anything 712 topEditor = newEditor; 713 return; 714 } 715 716 // Remove the contributions of the old editor 717 if (topEditor != null) { 718 deactivateContributions(topEditor, true); 719 } 720 721 // Show (disabled) the contributions of the new editor 722 if (newEditor != null) { 723 activateContributions(newEditor, false); 724 } 725 726 List<IActionSetDescriptor> newActionSets = calculateActionSets(activePart, newEditor); 727 if (!updateActionSets(newActionSets)) { 728 updateActionBars(); 729 } 730 731 topEditor = newEditor; 732 } 733 734 /** 735 * Activates the contributions of the given part. If <code>enable</code> is 736 * <code>true</code> the contributions are visible and enabled, otherwise they 737 * are disabled. 738 * 739 * @param part the part whose contributions are to be activated 740 * @param enable <code>true</code> the contributions are to be enabled, not just 741 * visible. 742 */ activateContributions(IWorkbenchPart part, boolean enable)743 private void activateContributions(IWorkbenchPart part, boolean enable) { 744 PartSite site = (PartSite) part.getSite(); 745 site.activateActionBars(enable); 746 } 747 748 /** 749 * Deactivates the contributions of the given part. If <code>remove</code> is 750 * <code>true</code> the contributions are removed, otherwise they are disabled. 751 * 752 * @param part the part whose contributions are to be deactivated 753 * @param remove <code>true</code> the contributions are to be removed, not just 754 * disabled. 755 */ deactivateContributions(IWorkbenchPart part, boolean remove)756 private void deactivateContributions(IWorkbenchPart part, boolean remove) { 757 PartSite site = (PartSite) part.getSite(); 758 if (site != null) { 759 site.deactivateActionBars(remove); 760 } 761 } 762 763 /** 764 * Calculates the action sets to show for the given part and editor 765 * 766 * @param part the active part, may be <code>null</code> 767 * @param editor the current editor, may be <code>null</code>, may be the active 768 * part 769 * @return the new action sets 770 */ calculateActionSets(IWorkbenchPart part, IEditorPart editor)771 private List<IActionSetDescriptor> calculateActionSets(IWorkbenchPart part, IEditorPart editor) { 772 List<IActionSetDescriptor> newActionSets = new ArrayList<>(); 773 if (part != null) { 774 IActionSetDescriptor[] partActionSets = WorkbenchPlugin.getDefault().getActionSetRegistry() 775 .getActionSetsFor(part.getSite().getId()); 776 newActionSets.addAll(Arrays.asList(partActionSets)); 777 } 778 if (editor != null && editor != part) { 779 IActionSetDescriptor[] editorActionSets = WorkbenchPlugin.getDefault().getActionSetRegistry() 780 .getActionSetsFor(editor.getSite().getId()); 781 newActionSets.addAll(Arrays.asList(editorActionSets)); 782 } 783 return newActionSets; 784 } 785 786 /** 787 * Updates the actions we are showing for the active part and current editor. 788 * 789 * @param newActionSets the action sets to show 790 * @return <code>true</code> if the action sets changed 791 */ updateActionSets(List<IActionSetDescriptor> newActionSets)792 private boolean updateActionSets(List<IActionSetDescriptor> newActionSets) { 793 if (oldActionSets.equals(newActionSets)) { 794 return false; 795 } 796 797 IContextService service = legacyWindow.getService(IContextService.class); 798 try { 799 service.deferUpdates(true); 800 801 // show the new 802 for (IActionSetDescriptor newActionSet : newActionSets) { 803 actionSets.showAction(newActionSet); 804 } 805 806 // hide the old 807 for (IActionSetDescriptor oldActionSet : oldActionSets) { 808 actionSets.hideAction(oldActionSet); 809 } 810 811 oldActionSets = newActionSets; 812 813 } finally { 814 service.deferUpdates(false); 815 } 816 Perspective persp = getActivePerspective(); 817 if (persp == null) { 818 return false; 819 } 820 821 legacyWindow.updateActionSets(); // this calls updateActionBars 822 legacyWindow.firePerspectiveChanged(WorkbenchPage.this, getPerspective(), CHANGE_ACTION_SET_SHOW); 823 return true; 824 } 825 826 } 827 828 private EPartService partService; 829 830 private SelectionService selectionService; 831 832 private MApplication application; 833 834 private MWindow window; 835 836 private EModelService modelService; 837 838 private IEventBroker broker; 839 840 /** 841 * An event handler that listens for an MArea's widget being set so that we can 842 * install DND support into its control. 843 */ 844 private EventHandler widgetHandler = event -> { 845 Object element = event.getProperty(UIEvents.EventTags.ELEMENT); 846 Object newValue = event.getProperty(UIEvents.EventTags.NEW_VALUE); 847 848 if (element instanceof MArea) { 849 // If it's an MArea in this window install the DND handling 850 if (modelService.findElements(window, null, MArea.class).contains(element)) { 851 if (newValue instanceof Control) { 852 installAreaDropSupport((Control) newValue); 853 } 854 } 855 } else if (element instanceof MPart && newValue == null) { 856 // If it's a 'e4' part then remove the reference for it 857 MPart changedPart = (MPart) element; 858 Object impl = changedPart.getObject(); 859 if (impl != null && !(impl instanceof CompatibilityPart)) { 860 EditorReference eRef = getEditorReference(changedPart); 861 if (eRef != null) 862 editorReferences.remove(eRef); 863 ViewReference vRef = getViewReference(changedPart); 864 if (vRef != null) 865 viewReferences.remove(vRef); 866 } 867 } 868 }; 869 870 @Inject 871 @Optional handleMinimizedStacks(@IEventTopicUIEvents.ApplicationElement.TOPIC_TAGS) Event event)872 private void handleMinimizedStacks(@UIEventTopic(UIEvents.ApplicationElement.TOPIC_TAGS) Event event) { 873 Object changedObj = event.getProperty(EventTags.ELEMENT); 874 875 if (!(changedObj instanceof MToolControl)) 876 return; 877 878 final MToolControl minimizedStack = (MToolControl) changedObj; 879 880 // Note: The non-API type TrimStack is not imported to avoid 881 // https://bugs.eclipse.org/435521 882 if (!(minimizedStack.getObject() instanceof org.eclipse.e4.ui.workbench.addons.minmax.TrimStack)) 883 return; 884 885 org.eclipse.e4.ui.workbench.addons.minmax.TrimStack ts = (org.eclipse.e4.ui.workbench.addons.minmax.TrimStack) minimizedStack 886 .getObject(); 887 if (!(ts.getMinimizedElement() instanceof MPartStack)) 888 return; 889 890 MPartStack stack = (MPartStack) ts.getMinimizedElement(); 891 MUIElement stackSel = stack.getSelectedElement(); 892 MPart thePart = null; 893 if (stackSel instanceof MPart) { 894 thePart = (MPart) stackSel; 895 } else if (stackSel instanceof MPlaceholder) { 896 MPlaceholder ph = (MPlaceholder) stackSel; 897 if (ph.getRef() instanceof MPart) { 898 thePart = (MPart) ph.getRef(); 899 } 900 } 901 902 if (thePart == null) 903 return; 904 905 if (UIEvents.isADD(event)) { 906 if (UIEvents.contains(event, UIEvents.EventTags.NEW_VALUE, 907 org.eclipse.e4.ui.workbench.addons.minmax.TrimStack.MINIMIZED_AND_SHOWING)) { 908 firePartVisible(thePart); 909 } 910 } else if (UIEvents.isREMOVE(event)) { 911 if (UIEvents.contains(event, UIEvents.EventTags.OLD_VALUE, 912 org.eclipse.e4.ui.workbench.addons.minmax.TrimStack.MINIMIZED_AND_SHOWING)) { 913 firePartHidden(thePart); 914 } 915 } 916 } 917 918 /** 919 * Boolean field to determine whether DND support has been added to the shared 920 * area yet. 921 * 922 * @see #installAreaDropSupport(Control) 923 */ 924 private boolean dndSupportInstalled = false; 925 926 /** 927 * Constructs a page. <code>restoreState(IMemento)</code> should be called to 928 * restore this page from data stored in a persistance file. 929 * 930 * @param w the parent window 931 * @param input the page input 932 * @throws WorkbenchException 933 */ WorkbenchPage(WorkbenchWindow w, IAdaptable input)934 public WorkbenchPage(WorkbenchWindow w, IAdaptable input) throws WorkbenchException { 935 super(); 936 init(w, null, input, false); 937 } 938 939 /** 940 * Allow access to the UI model that this page is managing 941 * 942 * @return the MWindow element for this page 943 */ getWindowModel()944 public MWindow getWindowModel() { 945 return window; 946 947 } 948 949 /** 950 * Activates a part. The part will be brought to the front and given focus. 951 * 952 * @param part the part to activate 953 */ 954 @Override activate(IWorkbenchPart part)955 public void activate(IWorkbenchPart part) { 956 if (part == null || !certifyPart(part) || legacyWindow.isClosing()) { 957 return; 958 } 959 MPart mpart = findPart(part); 960 if (mpart != null) { 961 partService.activate(mpart); 962 actionSwitcher.updateActivePart(part); 963 } 964 } 965 966 /** 967 * Adds an IPartListener to the part service. 968 */ 969 @Override addPartListener(IPartListener l)970 public void addPartListener(IPartListener l) { 971 partListenerList.add(l); 972 } 973 974 /** 975 * Adds an IPartListener to the part service. 976 */ 977 @Override addPartListener(IPartListener2 l)978 public void addPartListener(IPartListener2 l) { 979 partListener2List.add(l); 980 } 981 982 /** 983 * Implements IWorkbenchPage 984 * 985 * @see org.eclipse.ui.IWorkbenchPage#addPropertyChangeListener(IPropertyChangeListener) 986 * @since 2.0 987 * @deprecated individual views should store a working set if needed and 988 * register a property change listener directly with the working set 989 * manager to receive notification when the view working set is 990 * removed. 991 */ 992 @Deprecated 993 @Override addPropertyChangeListener(IPropertyChangeListener listener)994 public void addPropertyChangeListener(IPropertyChangeListener listener) { 995 propertyChangeListeners.add(listener); 996 } 997 998 @Override addSelectionListener(ISelectionListener listener)999 public void addSelectionListener(ISelectionListener listener) { 1000 selectionService.addSelectionListener(listener); 1001 } 1002 1003 @Override addSelectionListener(String partId, ISelectionListener listener)1004 public void addSelectionListener(String partId, ISelectionListener listener) { 1005 selectionService.addSelectionListener(partId, listener); 1006 } 1007 1008 @Override addPostSelectionListener(ISelectionListener listener)1009 public void addPostSelectionListener(ISelectionListener listener) { 1010 selectionService.addPostSelectionListener(listener); 1011 } 1012 1013 @Override addPostSelectionListener(String partId, ISelectionListener listener)1014 public void addPostSelectionListener(String partId, ISelectionListener listener) { 1015 selectionService.addPostSelectionListener(partId, listener); 1016 } 1017 1018 /** 1019 * Moves a part forward in the Z order of a perspective so it is visible. If the 1020 * part is in the same stack as the active part, the new part is activated. 1021 * 1022 * @param part the part to bring to move forward 1023 */ 1024 @Override bringToTop(IWorkbenchPart part)1025 public void bringToTop(IWorkbenchPart part) { 1026 // Sanity check. 1027 MPart mpart = findPart(part); 1028 if (mpart != null) { 1029 partService.bringToTop(mpart); 1030 } 1031 } 1032 findPart(IWorkbenchPart part)1033 public MPart findPart(IWorkbenchPart part) { 1034 if (part == null) { 1035 return null; 1036 } 1037 1038 for (IViewReference reference : viewReferences) { 1039 if (part == reference.getPart(false)) { 1040 return ((WorkbenchPartReference) reference).getModel(); 1041 } 1042 } 1043 1044 for (IEditorReference reference : editorReferences) { 1045 if (part == reference.getPart(false)) { 1046 return ((WorkbenchPartReference) reference).getModel(); 1047 } 1048 } 1049 return null; 1050 } 1051 createEditorReferenceForPart(final MPart part, IEditorInput input, String editorId, IMemento memento)1052 public EditorReference createEditorReferenceForPart(final MPart part, IEditorInput input, String editorId, 1053 IMemento memento) { 1054 IEditorRegistry registry = legacyWindow.getWorkbench().getEditorRegistry(); 1055 EditorDescriptor descriptor = (EditorDescriptor) registry.findEditor(editorId); 1056 final EditorReference ref = new EditorReference(window.getContext(), this, part, input, descriptor, memento); 1057 addEditorReference(ref); 1058 ref.subscribe(); 1059 return ref; 1060 } 1061 getOrderedEditorReferences()1062 private List<EditorReference> getOrderedEditorReferences() { 1063 1064 List<EditorReference> editorRefs = new ArrayList<>(); 1065 List<MPart> visibleEditors = modelService.findElements(window, CompatibilityEditor.MODEL_ELEMENT_ID, 1066 MPart.class); 1067 for (MPart editor : visibleEditors) { 1068 if (editor.isToBeRendered()) { 1069 EditorReference ref = getEditorReference(editor); 1070 if (ref != null && !editorRefs.contains(ref)) { 1071 editorRefs.add(ref); 1072 } 1073 } 1074 } 1075 1076 return editorRefs; 1077 } 1078 getSortedEditorReferences()1079 List<EditorReference> getSortedEditorReferences() { 1080 return getSortedEditorReferences(false); 1081 } 1082 getSortedEditorReferences(boolean allPerspectives)1083 private List<EditorReference> getSortedEditorReferences(boolean allPerspectives) { 1084 List<EditorReference> sortedReferences = new ArrayList<>(); 1085 for (MPart part : activationList) { 1086 for (EditorReference ref : editorReferences) { 1087 if (ref.getModel() == part) { 1088 sortedReferences.add(ref); 1089 break; 1090 } 1091 } 1092 } 1093 1094 for (EditorReference ref : editorReferences) { 1095 if (!sortedReferences.contains(ref)) { 1096 sortedReferences.add(ref); 1097 } 1098 } 1099 1100 MPerspective currentPerspective = getCurrentPerspective(); 1101 if (currentPerspective != null) { 1102 int scope = allPerspectives ? WINDOW_SCOPE : EModelService.PRESENTATION; 1103 List<MPart> placeholders = modelService.findElements(window, CompatibilityEditor.MODEL_ELEMENT_ID, 1104 MPart.class, null, scope); 1105 List<EditorReference> visibleReferences = new ArrayList<>(); 1106 for (EditorReference reference : sortedReferences) { 1107 for (MPart placeholder : placeholders) { 1108 if (reference.getModel() == placeholder && placeholder.isToBeRendered()) { 1109 // only rendered placeholders are valid references 1110 visibleReferences.add(reference); 1111 } 1112 } 1113 } 1114 1115 return visibleReferences; 1116 } 1117 1118 return sortedReferences; 1119 } 1120 getInternalEditorReferences()1121 public List<EditorReference> getInternalEditorReferences() { 1122 return editorReferences; 1123 } 1124 getEditorReference(MPart part)1125 public EditorReference getEditorReference(MPart part) { 1126 for (EditorReference ref : editorReferences) { 1127 if (ref.getModel() == part) { 1128 return ref; 1129 } 1130 } 1131 return null; 1132 } 1133 getViewReference(MPart part)1134 public ViewReference getViewReference(MPart part) { 1135 for (ViewReference ref : viewReferences) { 1136 if (ref.getModel() == part) { 1137 return ref; 1138 } 1139 } 1140 return null; 1141 } 1142 contains(ViewReference reference)1143 private boolean contains(ViewReference reference) { 1144 for (ViewReference viewReference : viewReferences) { 1145 if (reference.getModel().getElementId().equals(viewReference.getModel().getElementId())) { 1146 return true; 1147 } 1148 } 1149 return false; 1150 } 1151 addViewReference(ViewReference reference)1152 public void addViewReference(ViewReference reference) { 1153 if (!contains(reference)) { 1154 viewReferences.add(reference); 1155 } 1156 } 1157 addEditorReference(EditorReference editorReference)1158 public void addEditorReference(EditorReference editorReference) { 1159 WorkbenchPage curPage = (WorkbenchPage) editorReference.getPage(); 1160 1161 // Ensure that the page is up-to-date 1162 if (curPage != this) { 1163 curPage.editorReferences.remove(editorReference); 1164 editorReference.setPage(this); 1165 } 1166 1167 // Avoid dups 1168 if (!editorReferences.contains(editorReference)) { 1169 editorReferences.add(editorReference); 1170 } 1171 } 1172 findDescriptor(String id)1173 MPartDescriptor findDescriptor(String id) { 1174 return modelService.getPartDescriptor(id); 1175 } 1176 1177 /** 1178 * Searches the workbench window for a part with the given view id and secondary 1179 * id (if desired) given the specified search rules. 1180 * 1181 * @param viewId the id of the view 1182 * @param secondaryId the secondary id of the view, or <code>null</code> if the 1183 * view to search for should be one without a secondary id 1184 * defined 1185 * @param searchFlags the desired search locations 1186 * @return the part with the specified view id and secondary id, or 1187 * <code>null</code> if it could not be found in this page's parent 1188 * workbench window 1189 * @see EModelService#findElements(MUIElement, String, Class, List, int) 1190 */ findPart(String viewId, int searchFlags)1191 private MPart findPart(String viewId, int searchFlags) { 1192 List<MPart> parts = modelService.findElements(getWindowModel(), viewId, MPart.class, null, searchFlags); 1193 if (parts.size() > 0) 1194 return parts.get(0); 1195 1196 return null; 1197 } 1198 convert(int mode)1199 PartState convert(int mode) { 1200 switch (mode) { 1201 case VIEW_ACTIVATE: 1202 return PartState.ACTIVATE; 1203 case VIEW_VISIBLE: 1204 return PartState.VISIBLE; 1205 case VIEW_CREATE: 1206 return PartState.CREATE; 1207 } 1208 throw new IllegalArgumentException(WorkbenchMessages.WorkbenchPage_IllegalViewMode); 1209 } 1210 1211 /** 1212 * Shows a view. 1213 * 1214 * Assumes that a busy cursor is active. 1215 */ busyShowView(String viewId, int mode)1216 protected IViewPart busyShowView(String viewId, int mode) throws PartInitException { 1217 switch (mode) { 1218 case VIEW_ACTIVATE: 1219 case VIEW_VISIBLE: 1220 case VIEW_CREATE: 1221 break; 1222 default: 1223 throw new IllegalArgumentException(WorkbenchMessages.WorkbenchPage_IllegalViewMode); 1224 } 1225 1226 MPart part = findPart(viewId, EModelService.ANYWHERE); 1227 if (part == null) { 1228 MPlaceholder ph = partService.createSharedPart(viewId, false); 1229 if (ph == null) { 1230 throw new PartInitException(NLS.bind(WorkbenchMessages.ViewFactory_couldNotCreate, viewId)); 1231 } 1232 1233 part = (MPart) ph.getRef(); 1234 part.setCurSharedRef(ph); 1235 } 1236 1237 part = showPart(mode, part); 1238 1239 ViewReference ref = getViewReference(part); 1240 if (ref == null) { 1241 throw new PartInitException(NLS.bind(WorkbenchMessages.ViewFactory_initException, viewId)); 1242 } 1243 return (IViewPart) ref.getPart(true); 1244 } 1245 showPart(int mode, MPart part)1246 private MPart showPart(int mode, MPart part) { 1247 switch (mode) { 1248 case VIEW_ACTIVATE: 1249 partService.showPart(part, PartState.ACTIVATE); 1250 if (part.getObject() instanceof CompatibilityView) { 1251 CompatibilityView compatibilityView = (CompatibilityView) part.getObject(); 1252 actionSwitcher.updateActivePart(getWrappedPart(compatibilityView)); 1253 } 1254 break; 1255 case VIEW_VISIBLE: 1256 MPart activePart = partService.getActivePart(); 1257 if (activePart == null) { 1258 partService.showPart(part, PartState.ACTIVATE); 1259 if (part.getObject() instanceof CompatibilityView) { 1260 CompatibilityView compatibilityView = (CompatibilityView) part.getObject(); 1261 actionSwitcher.updateActivePart(getWrappedPart(compatibilityView)); 1262 } 1263 } else { 1264 part = ((PartServiceImpl) partService).addPart(part); 1265 MPlaceholder activePlaceholder = activePart.getCurSharedRef(); 1266 MUIElement activePartParent = activePlaceholder == null ? activePart.getParent() 1267 : activePlaceholder.getParent(); 1268 partService.showPart(part, PartState.CREATE); 1269 if (part.getCurSharedRef() == null || part.getCurSharedRef().getParent() != activePartParent) { 1270 partService.bringToTop(part); 1271 } 1272 } 1273 break; 1274 case VIEW_CREATE: 1275 partService.showPart(part, PartState.CREATE); 1276 1277 // Report the visibility of the created part 1278 MStackElement sElement = part; 1279 if (part.getCurSharedRef() != null) 1280 sElement = part.getCurSharedRef(); 1281 MUIElement parentElement = sElement.getParent(); 1282 if (parentElement instanceof MPartStack) { 1283 MPartStack partStack = (MPartStack) parentElement; 1284 if (partStack.getSelectedElement() == sElement 1285 && !partStack.getTags().contains(IPresentationEngine.MINIMIZED)) { 1286 firePartVisible(part); 1287 } else { 1288 firePartHidden(part); 1289 } 1290 } else { 1291 firePartVisible(part); // Stand-alone part 1292 } 1293 break; 1294 } 1295 return part; 1296 } 1297 1298 /** 1299 * Returns whether a part exists in the current page. 1300 */ certifyPart(IWorkbenchPart part)1301 private boolean certifyPart(IWorkbenchPart part) { 1302 // Workaround for bug 22325 1303 if (part != null && !(part.getSite() instanceof PartSite)) { 1304 return false; 1305 } 1306 return true; 1307 } 1308 1309 /** 1310 * Closes this page. 1311 */ 1312 @Override close()1313 public boolean close() { 1314 final boolean[] ret = new boolean[1]; 1315 BusyIndicator.showWhile(null, () -> ret[0] = close(true, true)); 1316 return ret[0]; 1317 } 1318 closeAllSavedEditors()1319 public boolean closeAllSavedEditors() { 1320 // get the Saved editors 1321 IEditorReference editors[] = getEditorReferences(); 1322 IEditorReference savedEditors[] = new IEditorReference[editors.length]; 1323 int j = 0; 1324 for (IEditorReference editor : editors) { 1325 if (!editor.isDirty()) { 1326 savedEditors[j++] = editor; 1327 } 1328 } 1329 // there are no unsaved editors 1330 if (j == 0) { 1331 return true; 1332 } 1333 IEditorReference[] newSaved = new IEditorReference[j]; 1334 System.arraycopy(savedEditors, 0, newSaved, 0, j); 1335 return closeEditors(newSaved, false); 1336 } 1337 1338 /** 1339 * See IWorkbenchPage 1340 */ 1341 @Override closeAllEditors(boolean save)1342 public boolean closeAllEditors(boolean save) { 1343 return closeEditors(getEditorReferences(), save); 1344 } 1345 1346 /** 1347 * See IWorkbenchPage 1348 */ 1349 @Override closeEditors(IEditorReference[] refArray, boolean save)1350 public boolean closeEditors(IEditorReference[] refArray, boolean save) { 1351 if (refArray.length == 0) { 1352 return true; 1353 } 1354 1355 // Check if we're being asked to close any parts that are already closed 1356 // or cannot 1357 // be closed at this time 1358 ArrayList<IEditorReference> editorRefs = new ArrayList<>(); 1359 for (IEditorReference reference : refArray) { 1360 // If we're in the middle of creating this part, this is a 1361 // programming error. Abort the entire 1362 // close operation. This usually occurs if someone tries to open a 1363 // dialog in a method that 1364 // isn't allowed to do so, and a *syncExec tries to close the part. 1365 // If this shows up in a log 1366 // file with a dialog's event loop on the stack, then the code that 1367 // opened the dialog is usually 1368 // at fault. 1369 if (reference == partBeingActivated) { 1370 WorkbenchPlugin.log(new RuntimeException("WARNING: Blocked recursive attempt to close part " //$NON-NLS-1$ 1371 + partBeingActivated.getId() + " while still in the middle of activating it")); //$NON-NLS-1$ 1372 return false; 1373 } 1374 1375 if (reference instanceof WorkbenchPartReference) { 1376 WorkbenchPartReference ref = (WorkbenchPartReference) reference; 1377 1378 // If we're being asked to close a part that is disposed (ie: 1379 // already closed), 1380 // skip it and proceed with closing the remaining parts. 1381 if (ref.isDisposed()) { 1382 continue; 1383 } 1384 } 1385 1386 editorRefs.add(reference); 1387 } 1388 1389 // if active navigation position belongs to an editor being closed, 1390 // update it 1391 // (The navigation position for an editor N was updated as an editor N + 1392 // 1 1393 // was activated. As a result, all but the last editor have up-to-date 1394 // navigation positions.) 1395 for (IEditorReference ref : editorRefs) { 1396 IEditorPart oldPart = ref.getEditor(false); 1397 if (oldPart == null) 1398 continue; 1399 if (navigationHistory.updateActive(oldPart)) 1400 break; // updated - skip the rest 1401 } 1402 1403 // notify the model manager before the close 1404 List<IWorkbenchPart> partsToClose = new ArrayList<>(); 1405 for (IEditorReference ref : editorRefs) { 1406 IEditorPart refPart = ref.getEditor(false); 1407 if (refPart != null) { 1408 partsToClose.add(refPart); 1409 } 1410 } 1411 1412 boolean confirm = true; 1413 SaveablesList modelManager = null; 1414 Object postCloseInfo = null; 1415 if (partsToClose.size() > 0) { 1416 modelManager = (SaveablesList) getWorkbenchWindow().getService(ISaveablesLifecycleListener.class); 1417 // this may prompt for saving and return null if the user canceled: 1418 postCloseInfo = modelManager.preCloseParts(partsToClose, save, getWorkbenchWindow()); 1419 if (postCloseInfo == null) { 1420 return false; 1421 } 1422 confirm = false; 1423 } 1424 1425 // Fire pre-removal changes 1426 for (IEditorReference ref : editorRefs) { 1427 // Notify interested listeners before the close 1428 legacyWindow.firePerspectiveChanged(this, getPerspective(), ref, CHANGE_EDITOR_CLOSE); 1429 1430 } 1431 1432 deferUpdates(true); 1433 try { 1434 if (modelManager != null) { 1435 modelManager.postClose(postCloseInfo); 1436 } 1437 1438 // Close all editors. 1439 for (Iterator<IEditorReference> it = editorRefs.iterator(); it.hasNext();) { 1440 IEditorReference ref = it.next(); 1441 // hide editors that haven't been instantiated first 1442 if (ref.getPart(false) == null) { 1443 if (!(hidePart(((EditorReference) ref).getModel(), false, confirm, false, false))) { 1444 return false; 1445 } 1446 // hidden successfully, remove it from the list 1447 it.remove(); 1448 } 1449 } 1450 1451 MPart activePart = findPart(getActiveEditor()); 1452 boolean closeActivePart = false; 1453 // now hide all instantiated editors 1454 for (IEditorReference editorRef : editorRefs) { 1455 MPart model = ((EditorReference) editorRef).getModel(); 1456 if (activePart == model) { 1457 closeActivePart = true; 1458 } else if (!(hidePart(model, false, confirm, false, false))) { 1459 // saving should've been handled earlier above 1460 return false; 1461 } 1462 } 1463 1464 // close the active part last to minimize activation churn 1465 if (closeActivePart) { 1466 if (!(hidePart(activePart, false, confirm, false))) { 1467 return false; 1468 } 1469 } 1470 } finally { 1471 deferUpdates(false); 1472 } 1473 1474 // Notify interested listeners after the close 1475 legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_EDITOR_CLOSE); 1476 1477 // Return true on success. 1478 return true; 1479 } 1480 closeEditor(IEditorReference editor)1481 public boolean closeEditor(IEditorReference editor) { 1482 if (getInternalEditorReferences().contains(editor)) { 1483 MPart part = ((EditorReference) editor).getModel(); 1484 hidePart(part, false, false, false, false); 1485 1486 MElementContainer<MUIElement> parent = part.getParent(); 1487 if (parent != null) { 1488 parent.getChildren().remove(part); 1489 } 1490 return true; 1491 } 1492 return false; 1493 } 1494 hidePart(MPart part, boolean save, boolean confirm, boolean force)1495 private boolean hidePart(MPart part, boolean save, boolean confirm, boolean force) { 1496 return hidePart(part, save, confirm, force, true); 1497 } 1498 hidePart(MPart part, boolean save, boolean confirm, boolean force, boolean local)1499 private boolean hidePart(MPart part, boolean save, boolean confirm, boolean force, boolean local) { 1500 if (!partService.getParts().contains(part)) { 1501 if (local) { 1502 return false; 1503 } 1504 part.setToBeRendered(false); 1505 return true; 1506 } 1507 1508 Object clientObject = part.getObject(); 1509 if (!(clientObject instanceof CompatibilityPart)) { 1510 // either not a 3.x part or it's an e4 part, should still hide it 1511 if (save) { 1512 // save as necessary 1513 if (partService.savePart(part, confirm)) { 1514 partService.hidePart(part, force); 1515 return true; 1516 } 1517 return false; 1518 } 1519 partService.hidePart(part, force); 1520 return true; 1521 } 1522 1523 IWorkbenchPart workbenchPart = getWrappedPart((CompatibilityPart) clientObject); 1524 if (save && workbenchPart != null) { 1525 ISaveablePart saveablePart = SaveableHelper.getSaveable(workbenchPart); 1526 if (saveablePart != null) { 1527 if (saveablePart.isSaveOnCloseNeeded()) { 1528 if (!saveSaveable(saveablePart, workbenchPart, confirm, true)) { 1529 return false; 1530 } 1531 } 1532 } 1533 } 1534 1535 for (IViewReference viewRef : viewReferences) { 1536 if (workbenchPart == viewRef.getPart(false)) { 1537 partService.hidePart(part, force); 1538 return true; 1539 } 1540 } 1541 1542 for (IEditorReference viewRef : editorReferences) { 1543 if (workbenchPart == viewRef.getPart(false)) { 1544 partService.hidePart(part, force); 1545 return true; 1546 } 1547 } 1548 return false; 1549 } 1550 1551 /** 1552 * Enables or disables listener notifications. This is used to delay listener 1553 * notifications until the end of a public method. 1554 * 1555 * @param shouldDefer 1556 */ deferUpdates(boolean shouldDefer)1557 private void deferUpdates(boolean shouldDefer) { 1558 if (shouldDefer) { 1559 if (deferCount == 0) { 1560 startDeferring(); 1561 } 1562 deferCount++; 1563 } else { 1564 deferCount--; 1565 if (deferCount == 0) { 1566 handleDeferredEvents(); 1567 } 1568 } 1569 } 1570 startDeferring()1571 private void startDeferring() { 1572 // TODO compat: do we defer events 1573 } 1574 handleDeferredEvents()1575 private void handleDeferredEvents() { 1576 // TODO compat: do we handler defered events 1577 } 1578 closeEditor(IEditorReference editorRef, boolean save)1579 public boolean closeEditor(IEditorReference editorRef, boolean save) { 1580 return closeEditors(new IEditorReference[] { editorRef }, save); 1581 } 1582 1583 /** 1584 * See IWorkbenchPage#closeEditor 1585 */ 1586 @Override closeEditor(IEditorPart editor, boolean save)1587 public boolean closeEditor(IEditorPart editor, boolean save) { 1588 IWorkbenchPartReference ref = getReference(editor); 1589 if (ref instanceof IEditorReference) { 1590 return closeEditors(new IEditorReference[] { (IEditorReference) ref }, save); 1591 } 1592 return false; 1593 } 1594 1595 /** 1596 * Closes the specified perspective. 1597 * 1598 * @param desc the perspective to close 1599 * @param perspectiveId the id of the perspective being closed 1600 * @param saveParts <code>true</code> if dirty parts should be prompted for 1601 * its contents to be saved, <code>false</code> otherwise 1602 */ closePerspective(IPerspectiveDescriptor desc, String perspectiveId, boolean saveParts)1603 private void closePerspective(IPerspectiveDescriptor desc, String perspectiveId, boolean saveParts) { 1604 MPerspective persp = (MPerspective) modelService.find(perspectiveId, window); 1605 // check to ensure this perspective actually exists in this window 1606 if (persp != null) { 1607 if (saveParts) { 1608 List<IWorkbenchPart> partsToSave = new ArrayList<>(); 1609 // retrieve all parts under the specified perspective 1610 List<MPart> parts = modelService.findElements(persp, null, MPart.class); 1611 if (!parts.isEmpty()) { 1612 // filter out any parts that are visible in any other 1613 // perspectives 1614 for (MPerspective perspective : getPerspectiveStack().getChildren()) { 1615 if (perspective != persp) { 1616 parts.removeAll(modelService.findElements(perspective, null, MPart.class)); 1617 } 1618 } 1619 1620 if (!parts.isEmpty()) { 1621 for (Iterator<MPart> it = parts.iterator(); it.hasNext();) { 1622 MPart part = it.next(); 1623 if (part.isDirty()) { 1624 Object object = part.getObject(); 1625 if (object instanceof CompatibilityPart) { 1626 IWorkbenchPart workbenchPart = getWrappedPart((CompatibilityPart) object); 1627 if (workbenchPart == null) { 1628 continue; 1629 } 1630 ISaveablePart saveablePart = SaveableHelper.getSaveable(workbenchPart); 1631 if (saveablePart != null) { 1632 if (!saveablePart.isSaveOnCloseNeeded()) { 1633 part.setDirty(false); 1634 it.remove(); 1635 } else { 1636 partsToSave.add(workbenchPart); 1637 } 1638 } 1639 } 1640 } else { 1641 it.remove(); 1642 } 1643 } 1644 1645 if (!partsToSave.isEmpty()) { 1646 if (!saveAll(partsToSave, true, true, false, legacyWindow, legacyWindow)) { 1647 // user cancel 1648 return; 1649 } 1650 } 1651 } 1652 } 1653 } 1654 1655 // Remove from caches 1656 sortedPerspectives.remove(desc); 1657 // check if we're closing the currently active perspective 1658 if (getPerspectiveStack().getSelectedElement() == persp && !sortedPerspectives.isEmpty()) { 1659 // get the perspective that was last active and set it 1660 IPerspectiveDescriptor lastActive = sortedPerspectives.get(sortedPerspectives.size() - 1); 1661 if (lastActive != null) { 1662 setPerspective(lastActive); 1663 } 1664 } 1665 modelService.removePerspectiveModel(persp, window); 1666 modelToPerspectiveMapping.remove(persp); 1667 1668 legacyWindow.firePerspectiveClosed(this, desc); 1669 } 1670 } 1671 1672 @Override closePerspective(IPerspectiveDescriptor desc, boolean saveParts, boolean closePage)1673 public void closePerspective(IPerspectiveDescriptor desc, boolean saveParts, boolean closePage) { 1674 closePerspective(desc, desc.getId(), saveParts, closePage); 1675 } 1676 closePerspective(IPerspectiveDescriptor desc, String perspectiveId, boolean saveParts, boolean closePage)1677 public void closePerspective(IPerspectiveDescriptor desc, String perspectiveId, boolean saveParts, 1678 boolean closePage) { 1679 MPerspective persp = (MPerspective) modelService.find(perspectiveId, window); 1680 // check to ensure this perspective actually exists in this window 1681 if (persp != null) { 1682 persp.getTags().add("PerspClosing"); //$NON-NLS-1$ 1683 try { 1684 MPerspectiveStack perspectiveStack = modelService.findElements(window, null, MPerspectiveStack.class) 1685 .get(0); 1686 if (perspectiveStack.getChildren().size() == 1) { 1687 closeAllPerspectives(saveParts, closePage); 1688 } else { 1689 closePerspective(desc, perspectiveId, saveParts); 1690 } 1691 } finally { 1692 persp.getTags().remove("PerspClosing"); //$NON-NLS-1$ 1693 } 1694 } 1695 } 1696 1697 @Override closeAllPerspectives(boolean saveEditors, boolean closePage)1698 public void closeAllPerspectives(boolean saveEditors, boolean closePage) { 1699 boolean okToProceed = closeAllEditors(true); 1700 if (okToProceed) { 1701 List<MPerspective> kids = new ArrayList<>(_perspectiveStack.getChildren()); 1702 MPerspective curPersp = _perspectiveStack.getSelectedElement(); 1703 for (MPerspective persp : kids) { 1704 if (persp != curPersp) { 1705 closePerspective(getPerspectiveDesc(persp.getElementId()), persp.getElementId(), false); 1706 } 1707 } 1708 if (curPersp != null) { 1709 closePerspective(getPerspectiveDesc(curPersp.getElementId()), curPersp.getElementId(), false); 1710 } 1711 if (closePage) { 1712 close(); 1713 } 1714 } 1715 } 1716 close(boolean save, boolean unsetPage)1717 private boolean close(boolean save, boolean unsetPage) { 1718 if (save && !saveAllEditors(true, true, true)) { 1719 return false; 1720 } 1721 1722 if (!legacyWindow.isClosing()) { 1723 Collection<MPart> partsToHide = partService.getParts(); 1724 // workaround for bug 455281 1725 List<MPart> partsOutsidePersp = modelService.findElements(window, null, MPart.class, null, 1726 EModelService.OUTSIDE_PERSPECTIVE); 1727 partsToHide.removeAll(partsOutsidePersp); 1728 1729 for (MPart part : partsToHide) { 1730 // no save, no confirm, force 1731 hidePart(part, false, true, true); 1732 } 1733 MPerspectiveStack perspectiveStack = modelService.findElements(window, null, MPerspectiveStack.class) 1734 .get(0); 1735 MPerspective current = perspectiveStack.getSelectedElement(); 1736 for (Object perspective : perspectiveStack.getChildren().toArray()) { 1737 if (perspective != current) { 1738 modelService.removePerspectiveModel((MPerspective) perspective, window); 1739 } 1740 } 1741 1742 if (current != null) { 1743 modelService.removePerspectiveModel(current, window); 1744 } 1745 } 1746 1747 for (ViewReference vr : viewReferences) { 1748 vr.setPage(null); 1749 } 1750 viewReferences.clear(); 1751 for (EditorReference er : editorReferences) { 1752 er.setPage(null); 1753 } 1754 editorReferences.clear(); 1755 sortedPerspectives.clear(); 1756 modelToPerspectiveMapping.clear(); 1757 1758 if (unsetPage) { 1759 if (!legacyWindow.isClosing()) { 1760 legacyWindow.setActivePage(null); 1761 } 1762 partService.removePartListener(e4PartListener); 1763 broker.unsubscribe(selectionHandler); 1764 broker.unsubscribe(widgetHandler); 1765 broker.unsubscribe(referenceRemovalEventHandler); 1766 broker.unsubscribe(firingHandler); 1767 broker.unsubscribe(childrenHandler); 1768 partEvents.clear(); 1769 1770 partListenerList.clear(); 1771 partListener2List.clear(); 1772 propertyChangeListeners.clear(); 1773 1774 selectionService.dispose(); 1775 if (!legacyWindow.isClosing()) { 1776 ContextInjectionFactory.uninject(this, window.getContext()); 1777 } 1778 } 1779 if (workingSetPropertyChangeListener != null) { 1780 WorkbenchPlugin.getDefault().getWorkingSetManager() 1781 .removePropertyChangeListener(workingSetPropertyChangeListener); 1782 workingSetPropertyChangeListener = null; 1783 } 1784 _perspectiveStack = null; 1785 actionBars = null; 1786 actionSets = null; 1787 actionSwitcher.activePart = null; 1788 actionSwitcher.topEditor = null; 1789 activationList.clear(); 1790 aggregateWorkingSet = null; 1791 application = null; 1792 broker = null; 1793 childrenHandler = null; 1794 composite = null; 1795 firingHandler = null; 1796 input = null; 1797 legacyWindow = null; 1798 // modelService = null; 1799 navigationHistory = null; 1800 pageChangedListener = null; 1801 partBeingActivated = null; 1802 partEvents.clear(); 1803 partService = null; 1804 referenceRemovalEventHandler = null; 1805 selectionHandler = null; 1806 selectionService = null; 1807 sortedPerspectives.clear(); 1808 tracker = null; 1809 widgetHandler = null; 1810 // window = null; 1811 workingSet = null; 1812 return true; 1813 } 1814 1815 /** 1816 * Forces all perspectives on the page to zoom out. 1817 */ unzoomAllPerspectives()1818 public void unzoomAllPerspectives() { 1819 // TODO compat: we have no min/max behaviour 1820 } 1821 1822 /** 1823 * Cleanup. 1824 */ dispose()1825 public void dispose() { 1826 legacyWindow = null; 1827 1828 // // Always unzoom 1829 // if (isZoomed()) { 1830 // zoomOut(); 1831 // } 1832 // 1833 // // makeActiveEditor(null); 1834 // // makeActive(null); 1835 // 1836 // // Close and dispose the editors. 1837 // closeAllEditors(false); 1838 // 1839 // // Need to make sure model data is cleaned up when the page is 1840 // // disposed. Collect all the views on the page and notify the 1841 // // saveable list of a pre/post close. This will free model data. 1842 // IWorkbenchPartReference[] partsToClose = getOpenParts(); 1843 // List dirtyParts = new ArrayList(partsToClose.length); 1844 // for (int i = 0; i < partsToClose.length; i++) { 1845 // IWorkbenchPart part = partsToClose[i].getPart(false); 1846 // if (part != null && part instanceof IViewPart) { 1847 // dirtyParts.add(part); 1848 // } 1849 // } 1850 // SaveablesList saveablesList = (SaveablesList) 1851 // getWorkbenchWindow().getWorkbench().getService(ISaveablesLifecycleListener.class); 1852 // Object postCloseInfo = saveablesList.preCloseParts(dirtyParts, 1853 // false,getWorkbenchWindow()); 1854 // saveablesList.postClose(postCloseInfo); 1855 // 1856 // // Get rid of perspectives. This will close the views. 1857 // Iterator itr = perspList.iterator(); 1858 // while (itr.hasNext()) { 1859 // Perspective perspective = (Perspective) itr.next(); 1860 // legacyWindow.firePerspectiveClosed(this, perspective.getDesc()); 1861 // perspective.dispose(); 1862 // } 1863 // perspList = new PerspectiveList(); 1864 // 1865 // // Capture views. 1866 // IViewReference refs[] = viewFactory.getViews(); 1867 // 1868 // if (refs.length > 0) { 1869 // // Dispose views. 1870 // for (int i = 0; i < refs.length; i++) { 1871 // final WorkbenchPartReference ref = (WorkbenchPartReference) refs[i]; 1872 // //partList.removePart(ref); 1873 // //firePartClosed(refs[i]); 1874 // SafeRunner.run(new SafeRunnable() { 1875 // public void run() { 1876 // // WorkbenchPlugin.log(new Status(IStatus.WARNING, 1877 // WorkbenchPlugin.PI_WORKBENCH, 1878 //// Status.OK, "WorkbenchPage leaked a refcount for view " + ref.getId(), 1879 // null)); //$NON-NLS-1$//$NON-NLS-2$ 1880 // 1881 // ref.dispose(); 1882 // } 1883 // 1884 // public void handleException(Throwable e) { 1885 // } 1886 // }); 1887 // } 1888 // } 1889 // 1890 // activationList = new ActivationList(); 1891 // 1892 // // Get rid of editor presentation. 1893 // editorPresentation.dispose(); 1894 // 1895 // // Get rid of composite. 1896 // composite.dispose(); 1897 // 1898 // navigationHistory.dispose(); 1899 // 1900 // stickyViewMan.clear(); 1901 // 1902 // if (tracker != null) { 1903 // tracker.close(); 1904 // } 1905 // 1906 // // if we're destroying a window in a non-shutdown situation then we 1907 // should 1908 // // clean up the working set we made. 1909 // if (!legacyWindow.getWorkbench().isClosing()) { 1910 // if (aggregateWorkingSet != null) { 1911 // PlatformUI.getWorkbench().getWorkingSetManager().removeWorkingSet(aggregateWorkingSet); 1912 // } 1913 // } 1914 } 1915 1916 /** 1917 * @return NavigationHistory 1918 */ 1919 @Override getNavigationHistory()1920 public INavigationHistory getNavigationHistory() { 1921 return navigationHistory; 1922 } 1923 editActionSets()1924 public boolean editActionSets() { 1925 Perspective persp = getActivePerspective(); 1926 if (persp == null) { 1927 return false; 1928 } 1929 1930 // Create list dialog. 1931 CustomizePerspectiveDialog dlg = legacyWindow.createCustomizePerspectiveDialog(persp, window.getContext()); 1932 // Open. 1933 boolean ret = (dlg.open() == Window.OK); 1934 if (ret) { 1935 legacyWindow.updateActionSets(); 1936 legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_RESET); 1937 legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_RESET_COMPLETE); 1938 } 1939 return ret; 1940 } 1941 1942 /** 1943 * See IWorkbenchPage@findView. 1944 */ 1945 @Override findView(String id)1946 public IViewPart findView(String id) { 1947 IViewReference ref = findViewReference(id); 1948 if (ref == null) { 1949 return null; 1950 } 1951 return ref.getView(true); 1952 } 1953 1954 @Override findViewReference(String viewId)1955 public IViewReference findViewReference(String viewId) { 1956 for (IViewReference reference : getViewReferences()) { 1957 ViewReference ref = (ViewReference) reference; 1958 if (viewId.equals(ref.getModel().getElementId())) { 1959 return reference; 1960 } 1961 } 1962 return null; 1963 } 1964 1965 @Override findViewReference(String viewId, String secondaryId)1966 public IViewReference findViewReference(String viewId, String secondaryId) { 1967 String compoundId = viewId; 1968 if (secondaryId != null && secondaryId.length() > 0) 1969 compoundId += ":" + secondaryId; //$NON-NLS-1$ 1970 return findViewReference(compoundId); 1971 } 1972 createViewReferenceForPart(final MPart part, String viewId)1973 public void createViewReferenceForPart(final MPart part, String viewId) { 1974 // If the id contains a ':' use the part before it as the descriptor id 1975 int colonIndex = viewId.indexOf(':'); 1976 String descId = colonIndex == -1 ? viewId : viewId.substring(0, colonIndex); 1977 1978 IViewDescriptor desc = getWorkbenchWindow().getWorkbench().getViewRegistry().find(descId); 1979 final ViewReference ref = new ViewReference(window.getContext(), this, part, (ViewDescriptor) desc); 1980 if (contains(ref)) { 1981 return; 1982 } 1983 1984 IEclipseContext partContext = part.getContext(); 1985 if (partContext == null) { 1986 ref.subscribe(); 1987 } else { 1988 partContext.set(ViewReference.class.getName(), ref); 1989 } 1990 addViewReference(ref); 1991 } 1992 1993 /** 1994 * Notify property change listeners about a property change. 1995 * 1996 * @param changeId the change id 1997 * @param oldValue old property value 1998 * @param newValue new property value 1999 */ firePropertyChange(String changeId, Object oldValue, Object newValue)2000 private void firePropertyChange(String changeId, Object oldValue, Object newValue) { 2001 2002 UIListenerLogging.logPagePropertyChanged(this, changeId, oldValue, newValue); 2003 2004 PropertyChangeEvent event = new PropertyChangeEvent(this, changeId, oldValue, newValue); 2005 2006 for (IPropertyChangeListener listener : propertyChangeListeners) { 2007 listener.propertyChange(event); 2008 } 2009 } 2010 2011 /* 2012 * Returns the action bars. 2013 */ getActionBars()2014 public IActionBars getActionBars() { 2015 if (actionBars == null) { 2016 actionBars = new WWinActionBars(legacyWindow); 2017 } 2018 return actionBars; 2019 } 2020 2021 /** 2022 * Returns an array of the visible action sets. 2023 * 2024 * @return an array of the currently visible action sets 2025 */ getActionSets()2026 public IActionSetDescriptor[] getActionSets() { 2027 Collection<?> collection = actionSets.getVisibleItems(); 2028 return collection.toArray(new IActionSetDescriptor[collection.size()]); 2029 } 2030 2031 /** 2032 * @see IWorkbenchPage 2033 */ 2034 @Override getActiveEditor()2035 public IEditorPart getActiveEditor() { 2036 IWorkbenchPart activePart = getActivePart(); 2037 if (activePart instanceof IEditorPart) { 2038 // if the currently active part is an editor, return it 2039 return (IEditorPart) activePart; 2040 } 2041 2042 if (!activationList.isEmpty()) { 2043 IEditorPart editor = findActiveEditor(); 2044 if (editor != null) { 2045 return editor; 2046 } 2047 } 2048 2049 MUIElement area = findSharedArea(); 2050 if (area instanceof MPlaceholder) { 2051 area = ((MPlaceholder) area).getRef(); 2052 } 2053 if (area != null && area.isVisible() && area.isToBeRendered()) { 2054 // we have a shared area, try iterating over its editors first 2055 List<MPart> editors = modelService.findElements(area, CompatibilityEditor.MODEL_ELEMENT_ID, MPart.class); 2056 for (MPart model : editors) { 2057 Object object = model.getObject(); 2058 if (object instanceof CompatibilityEditor) { 2059 CompatibilityEditor editor = (CompatibilityEditor) object; 2060 // see bug 308492 2061 if (!editor.isBeingDisposed() && isInArea(area, model)) { 2062 return ((CompatibilityEditor) object).getEditor(); 2063 } 2064 } 2065 } 2066 } 2067 2068 MPerspective perspective = getPerspectiveStack().getSelectedElement(); 2069 if (perspective == null) { 2070 return null; 2071 } 2072 2073 List<MPart> parts = modelService.findElements(perspective, CompatibilityEditor.MODEL_ELEMENT_ID, MPart.class, 2074 null); 2075 for (MPart part : parts) { 2076 Object object = part.getObject(); 2077 if (object instanceof CompatibilityEditor) { 2078 CompatibilityEditor editor = (CompatibilityEditor) object; 2079 // see bug 308492 2080 if (!editor.isBeingDisposed()) { 2081 if (isValid(perspective, part) || isValid(window, part)) { 2082 return ((CompatibilityEditor) object).getEditor(); 2083 } 2084 } 2085 } 2086 } 2087 return null; 2088 } 2089 2090 /** 2091 * Searches and returns an editor from the activation list that is being 2092 * displayed in the current presentation. If an editor is in the presentation 2093 * but is behind another part it will not be returned. 2094 * 2095 * @return an editor that is being shown in the current presentation and was 2096 * previously activated, editors that are behind another part in a stack 2097 * will not be returned 2098 */ findActiveEditor()2099 private IEditorPart findActiveEditor() { 2100 List<MPart> candidates = new ArrayList<>(activationList); 2101 MUIElement area = findSharedArea(); 2102 if (area instanceof MPlaceholder) { 2103 area = ((MPlaceholder) area).getRef(); 2104 } 2105 if (area != null && area.isVisible() && area.isToBeRendered()) { 2106 // we have a shared area, try iterating over its editors first 2107 List<MPart> editors = modelService.findElements(area, CompatibilityEditor.MODEL_ELEMENT_ID, MPart.class); 2108 for (Iterator<MPart> it = candidates.iterator(); it.hasNext();) { 2109 MPart model = it.next(); 2110 if (!editors.contains(model)) { 2111 continue; 2112 } 2113 2114 Object object = model.getObject(); 2115 if (object instanceof CompatibilityEditor) { 2116 CompatibilityEditor editor = (CompatibilityEditor) object; 2117 // see bug 308492 2118 if (!editor.isBeingDisposed() && isInArea(area, model)) { 2119 return ((CompatibilityEditor) object).getEditor(); 2120 } 2121 } 2122 it.remove(); 2123 } 2124 } 2125 2126 MPerspective perspective = getPerspectiveStack().getSelectedElement(); 2127 for (MPart model : activationList) { 2128 Object object = model.getObject(); 2129 if (object instanceof CompatibilityEditor) { 2130 CompatibilityEditor editor = (CompatibilityEditor) object; 2131 // see bug 308492 2132 if (!editor.isBeingDisposed()) { 2133 if (isValid(perspective, model) || isValid(window, model)) { 2134 return ((CompatibilityEditor) object).getEditor(); 2135 } 2136 } 2137 } 2138 } 2139 return null; 2140 } 2141 isInArea(MUIElement area, MUIElement element)2142 private boolean isInArea(MUIElement area, MUIElement element) { 2143 if (!element.isToBeRendered() || !element.isVisible()) { 2144 return false; 2145 } 2146 2147 if (element == area) { 2148 return true; 2149 } 2150 2151 MElementContainer<?> parent = element.getParent(); 2152 if (parent == null || parent instanceof MPerspective || parent instanceof MWindow) { 2153 return false; 2154 } else if (parent instanceof MGenericStack) { 2155 return parent.getSelectedElement() == element ? isValid(area, parent) : false; 2156 } 2157 2158 return isValid(area, parent); 2159 } 2160 isValid(MUIElement ancestor, MUIElement element)2161 private boolean isValid(MUIElement ancestor, MUIElement element) { 2162 if (!element.isToBeRendered() || !element.isVisible()) { 2163 return false; 2164 } 2165 2166 if (element == ancestor) { 2167 return true; 2168 } 2169 2170 MElementContainer<?> parent = element.getParent(); 2171 if (parent == null) { 2172 // might be a detached window 2173 if (element instanceof MWindow) { 2174 parent = (MElementContainer<?>) ((EObject) element).eContainer(); 2175 } 2176 2177 if (parent == null) { 2178 return false; 2179 } 2180 } 2181 2182 if (parent instanceof MGenericStack) { 2183 return parent.getSelectedElement() == element ? isValid(ancestor, parent) : false; 2184 } 2185 2186 return isValid(ancestor, parent); 2187 } 2188 2189 @Override getActivePart()2190 public IWorkbenchPart getActivePart() { 2191 if (partService == null) { 2192 return null; 2193 } 2194 MPart part = partService.getActivePart(); 2195 return getWorkbenchPart(part); 2196 } 2197 2198 @Override getActivePartReference()2199 public IWorkbenchPartReference getActivePartReference() { 2200 IWorkbenchPart part = getActivePart(); 2201 return part == null ? null : getReference(part); 2202 } 2203 getClientComposite()2204 public Composite getClientComposite() { 2205 return composite; 2206 } 2207 2208 @Override getDirtyEditors()2209 public IEditorPart[] getDirtyEditors() { 2210 List<IEditorPart> dirtyEditors = new ArrayList<>(); 2211 for (IEditorReference editorRef : editorReferences) { 2212 IEditorPart editor = editorRef.getEditor(false); 2213 if (editor != null && editor.isDirty()) { 2214 dirtyEditors.add(editor); 2215 } 2216 } 2217 return dirtyEditors.toArray(new IEditorPart[dirtyEditors.size()]); 2218 } 2219 2220 @Override findEditor(IEditorInput input)2221 public IEditorPart findEditor(IEditorInput input) { 2222 IEditorReference[] references = findEditors(input, null, MATCH_INPUT); 2223 return references.length == 0 ? null : references[0].getEditor(true); 2224 } 2225 2226 @Override findEditors(IEditorInput input, String editorId, int matchFlags)2227 public IEditorReference[] findEditors(IEditorInput input, String editorId, int matchFlags) { 2228 List<EditorReference> filteredReferences = getSortedEditorReferences(); 2229 2230 switch (matchFlags) { 2231 case MATCH_INPUT: 2232 List<IEditorReference> editorRefs = new ArrayList<>(); 2233 for (EditorReference editorRef : filteredReferences) { 2234 checkEditor(input, editorRefs, editorRef); 2235 } 2236 return editorRefs.toArray(new IEditorReference[editorRefs.size()]); 2237 case MATCH_ID: 2238 editorRefs = new ArrayList<>(); 2239 for (IEditorReference editorRef : filteredReferences) { 2240 if (editorId.equals(editorRef.getId())) { 2241 editorRefs.add(editorRef); 2242 } 2243 } 2244 return editorRefs.toArray(new IEditorReference[editorRefs.size()]); 2245 default: 2246 if ((matchFlags & IWorkbenchPage.MATCH_ID) != 0 && (matchFlags & IWorkbenchPage.MATCH_INPUT) != 0) { 2247 editorRefs = new ArrayList<>(); 2248 for (EditorReference editorRef : filteredReferences) { 2249 if (editorRef.getId().equals(editorId)) { 2250 checkEditor(input, editorRefs, editorRef); 2251 } 2252 } 2253 return editorRefs.toArray(new IEditorReference[editorRefs.size()]); 2254 } 2255 return new IEditorReference[0]; 2256 } 2257 } 2258 checkEditor(IEditorInput input, List<IEditorReference> editorRefs, EditorReference editorRef)2259 private void checkEditor(IEditorInput input, List<IEditorReference> editorRefs, EditorReference editorRef) { 2260 EditorDescriptor descriptor = editorRef.getDescriptor(); 2261 if (descriptor != null) { 2262 IEditorMatchingStrategy strategy = descriptor.getEditorMatchingStrategy(); 2263 if (strategy != null && strategy.matches(editorRef, input)) { 2264 editorRefs.add(editorRef); 2265 return; 2266 } 2267 } 2268 2269 IEditorPart editor = editorRef.getEditor(false); 2270 if (editor == null) { 2271 try { 2272 String name = input.getName(); 2273 IPersistableElement persistable = input.getPersistable(); 2274 if (name == null || persistable == null) { 2275 return; 2276 } 2277 2278 String id = persistable.getFactoryId(); 2279 if (id != null && id.equals(editorRef.getFactoryId()) && name.equals(editorRef.getName()) 2280 && input.equals(editorRef.getEditorInput())) { 2281 editorRefs.add(editorRef); 2282 } 2283 } catch (PartInitException e) { 2284 WorkbenchPlugin.log(e); 2285 } 2286 } else if (editor.getEditorInput().equals(input)) { 2287 editorRefs.add(editorRef); 2288 } 2289 } 2290 2291 @Override getEditors()2292 public IEditorPart[] getEditors() { 2293 final IEditorReference[] editorReferences = getEditorReferences(); 2294 int length = editorReferences.length; 2295 IEditorPart[] editors = new IEditorPart[length]; 2296 for (int i = 0; i < length; i++) { 2297 editors[i] = editorReferences[i].getEditor(true); 2298 } 2299 return editors; 2300 } 2301 2302 @Override getEditorReferences()2303 public IEditorReference[] getEditorReferences() { 2304 List<EditorReference> references = getOrderedEditorReferences(); 2305 return references.toArray(new IEditorReference[references.size()]); 2306 } 2307 getSortedEditors()2308 public IEditorReference[] getSortedEditors() { 2309 IWorkbenchPartReference[] parts = getSortedParts(true, false, false); 2310 IEditorReference[] editors = new IEditorReference[parts.length]; 2311 System.arraycopy(parts, 0, editors, 0, parts.length); 2312 return editors; 2313 } 2314 getSortedParts()2315 public IWorkbenchPartReference[] getSortedParts() { 2316 return getSortedParts(true, true, false); 2317 } 2318 2319 /** 2320 * Returns a sorted array of references to editors and/or views from this page. 2321 * 2322 * @param editors include editors 2323 * @param views include views 2324 * @param allPerspectives if {@code false}, does not include parts from inactive 2325 * perspectives 2326 * @return a sorted array of references to editors and/or views 2327 */ getSortedParts(boolean editors, boolean views, boolean allPerspectives)2328 private IWorkbenchPartReference[] getSortedParts(boolean editors, boolean views, boolean allPerspectives) { 2329 if (!editors && !views) { 2330 return new IWorkbenchPartReference[0]; 2331 } 2332 2333 List<IWorkbenchPartReference> sortedReferences = new ArrayList<>(); 2334 IViewReference[] viewReferences = getViewReferences(allPerspectives); 2335 List<EditorReference> editorReferences = getSortedEditorReferences(allPerspectives); 2336 2337 activationLoop: for (MPart part : activationList) { 2338 if (views) { 2339 for (IViewReference ref : viewReferences) { 2340 if (((ViewReference) ref).getModel() == part) { 2341 sortedReferences.add(ref); 2342 continue activationLoop; 2343 } 2344 } 2345 } 2346 2347 if (editors) { 2348 for (EditorReference ref : editorReferences) { 2349 if (ref.getModel() == part) { 2350 sortedReferences.add(ref); 2351 break; 2352 } 2353 } 2354 } 2355 } 2356 2357 if (views) { 2358 for (IViewReference ref : viewReferences) { 2359 if (!sortedReferences.contains(ref)) { 2360 sortedReferences.add(ref); 2361 } 2362 } 2363 } 2364 2365 if (editors) { 2366 for (EditorReference ref : editorReferences) { 2367 if (!sortedReferences.contains(ref)) { 2368 sortedReferences.add(ref); 2369 } 2370 } 2371 } 2372 2373 return sortedReferences.toArray(new IWorkbenchPartReference[sortedReferences.size()]); 2374 } 2375 2376 /** 2377 * @see IWorkbenchPage 2378 */ 2379 @Override getInput()2380 public IAdaptable getInput() { 2381 return input; 2382 } 2383 2384 /** 2385 * Returns the page label. This is a combination of the page input and active 2386 * perspective. 2387 */ 2388 @Override getLabel()2389 public String getLabel() { 2390 String label = WorkbenchMessages.WorkbenchPage_UnknownLabel; 2391 IWorkbenchAdapter adapter = Adapters.adapt(input, IWorkbenchAdapter.class); 2392 if (adapter != null) { 2393 label = adapter.getLabel(input); 2394 } 2395 // Perspective persp = getActivePerspective(); 2396 // if (persp != null) { 2397 // label = NLS.bind(WorkbenchMessages.WorkbenchPage_PerspectiveFormat, 2398 // label, persp.getDesc().getLabel()); 2399 // } else if (deferredActivePersp != null) { 2400 // label = 2401 // NLS.bind(WorkbenchMessages.WorkbenchPage_PerspectiveFormat,label, 2402 // deferredActivePersp.getLabel()); 2403 // } 2404 return label; 2405 } 2406 2407 /** 2408 * Returns the perspective. 2409 */ 2410 @Override getPerspective()2411 public IPerspectiveDescriptor getPerspective() { 2412 MPerspectiveStack ps = getPerspectiveStack(); 2413 MPerspective curPersp = ps.getSelectedElement(); 2414 if (curPersp == null) 2415 return null; 2416 return getPerspectiveDesc(curPersp.getElementId()); 2417 } 2418 getPerspectiveDesc(String id)2419 public IPerspectiveDescriptor getPerspectiveDesc(String id) { 2420 IPerspectiveRegistry perspectiveRegistry = PlatformUI.getWorkbench().getPerspectiveRegistry(); 2421 // registry may be null on shutdown 2422 if (perspectiveRegistry == null) { 2423 return null; 2424 } 2425 return perspectiveRegistry.findPerspectiveWithId(id); 2426 } 2427 2428 @Override getSelection()2429 public ISelection getSelection() { 2430 return selectionService.getSelection(); 2431 } 2432 2433 @Override getSelection(String partId)2434 public ISelection getSelection(String partId) { 2435 return selectionService.getSelection(partId); 2436 } 2437 2438 /** 2439 * Returns the ids of the parts to list in the Show In... prompter. This is a 2440 * List of Strings. 2441 * 2442 * @return the ids of the parts that should be available in the 'Show In...' 2443 * prompt 2444 */ getShowInPartIds()2445 public ArrayList<?> getShowInPartIds() { 2446 MPerspective perspective = getPerspectiveStack().getSelectedElement(); 2447 return new ArrayList<>(ModeledPageLayout.getIds(perspective, ModeledPageLayout.SHOW_IN_PART_TAG)); 2448 } 2449 2450 /** 2451 * The user successfully performed a Show In... action on the specified part. 2452 * Update the list of Show In items accordingly. 2453 * 2454 * @param partId the id of the part that the action was performed on 2455 */ performedShowIn(String partId)2456 public void performedShowIn(String partId) { 2457 mruShowInPartIds.remove(partId); 2458 mruShowInPartIds.add(0, partId); 2459 } 2460 2461 /** 2462 * Sorts the given collection of show in target part ids in MRU order. 2463 * 2464 * @param partIds the collection of part ids to rearrange 2465 */ sortShowInPartIds(ArrayList<?> partIds)2466 public void sortShowInPartIds(ArrayList<?> partIds) { 2467 partIds.sort((ob1, ob2) -> { 2468 int index1 = mruShowInPartIds.indexOf(ob1); 2469 int index2 = mruShowInPartIds.indexOf(ob2); 2470 if (index1 != -1 && index2 == -1) 2471 return -1; 2472 if (index1 == -1 && index2 != -1) 2473 return 1; 2474 return index1 - index2; 2475 }); 2476 } 2477 2478 /** 2479 * See IWorkbenchPage. 2480 */ 2481 @Override getViewReferences()2482 public IViewReference[] getViewReferences() { 2483 return getViewReferences(false); 2484 } 2485 getViewReferences(boolean allPerspectives)2486 private IViewReference[] getViewReferences(boolean allPerspectives) { 2487 MPerspective perspective = getCurrentPerspective(); 2488 if (perspective != null) { 2489 int scope = allPerspectives ? WINDOW_SCOPE : EModelService.PRESENTATION; 2490 Set<MUIElement> parts = new HashSet<>(); 2491 List<MPlaceholder> placeholders = modelService.findElements(window, null, MPlaceholder.class, null, scope); 2492 parts.addAll(placeholders); 2493 parts.addAll(modelService.findElements(window, null, MPart.class, null, scope)); 2494 List<IViewReference> visibleReferences = new ArrayList<>(); 2495 for (ViewReference reference : viewReferences) { 2496 MPart model = reference.getModel(); 2497 // The part may be linked in either directly or via a 2498 // placeholder. In the latter case we can look 2499 // at the part's curSharedRef since we're only considering 2500 // parts visible in the current perspective 2501 if (parts.contains(model) && !shouldNotRenderPart(model)) { 2502 // only rendered placeholders are valid view references 2503 visibleReferences.add(reference); 2504 } 2505 } 2506 return visibleReferences.toArray(new IViewReference[visibleReferences.size()]); 2507 } 2508 return new IViewReference[0]; 2509 } 2510 2511 /** 2512 * @return {@code true} if the part should not be rendered or it has a current 2513 * shared reference that is not to be rendered <b>or</b> if a 2514 * placeholder for the part (in the current perspective) exists and is 2515 * not to be rendered. {@code false} otherwise, i.e. if the placeholders 2516 * of the part are to be rendered. 2517 */ shouldNotRenderPart(MPart part)2518 private boolean shouldNotRenderPart(MPart part) { 2519 if (!part.isToBeRendered()) { 2520 return true; 2521 } 2522 MPlaceholder curSharedRef = part.getCurSharedRef(); 2523 if (curSharedRef != null && !curSharedRef.isToBeRendered()) { 2524 return true; 2525 } 2526 MPlaceholder mPlaceholder = modelService.findPlaceholderFor(window, part); 2527 if (mPlaceholder != null && !mPlaceholder.isToBeRendered()) { 2528 return true; 2529 } 2530 return false; 2531 } 2532 2533 /** 2534 * See IWorkbenchPage. 2535 */ 2536 @Override getViews()2537 public IViewPart[] getViews() { 2538 IViewReference[] viewReferences = getViewReferences(); 2539 int length = viewReferences.length; 2540 IViewPart[] views = new IViewPart[length]; 2541 for (int i = 0; i < length; i++) { 2542 views[i] = viewReferences[i].getView(true); 2543 } 2544 return views; 2545 } 2546 2547 /** 2548 * See IWorkbenchPage. 2549 */ 2550 @Override getWorkbenchWindow()2551 public IWorkbenchWindow getWorkbenchWindow() { 2552 return legacyWindow; 2553 } 2554 2555 /** 2556 * Implements IWorkbenchPage 2557 * 2558 * @see org.eclipse.ui.IWorkbenchPage#getWorkingSet() 2559 * @since 2.0 2560 * @deprecated individual views should store a working set if needed 2561 */ 2562 @Deprecated 2563 @Override getWorkingSet()2564 public IWorkingSet getWorkingSet() { 2565 return workingSet; 2566 } 2567 2568 /** 2569 * @see IWorkbenchPage 2570 */ 2571 @Override hideActionSet(String actionSetID)2572 public void hideActionSet(String actionSetID) { 2573 MPerspective mpersp = getCurrentPerspective(); 2574 if (mpersp == null) 2575 return; 2576 2577 Perspective persp = getActivePerspective(); 2578 if (persp != null) { 2579 ActionSetRegistry reg = WorkbenchPlugin.getDefault().getActionSetRegistry(); 2580 2581 IActionSetDescriptor desc = reg.findActionSet(actionSetID); 2582 if (desc != null) { 2583 persp.removeActionSet(desc); 2584 } 2585 legacyWindow.updateActionSets(); 2586 legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_ACTION_SET_HIDE); 2587 } 2588 String tag = ModeledPageLayout.ACTION_SET_TAG + actionSetID; 2589 addHiddenItems(tag); 2590 } 2591 2592 @Override hideView(IViewReference view)2593 public void hideView(IViewReference view) { 2594 if (view != null) { 2595 for (IViewReference reference : getViewReferences()) { 2596 if (reference == view) { 2597 hidePart(((ViewReference) view).getModel(), true, true, false); 2598 break; 2599 } 2600 } 2601 } 2602 } 2603 2604 @Override hideView(IViewPart view)2605 public void hideView(IViewPart view) { 2606 if (view != null) { 2607 MPart part = findPart(view); 2608 if (part != null) { 2609 hidePart(part, true, true, false); 2610 } 2611 } 2612 } 2613 2614 /** 2615 * Initialize the page. 2616 * 2617 * @param w the parent window 2618 * @param layoutID may be <code>null</code> if restoring from file 2619 * @param input the page input 2620 * @param openExtras whether to process the perspective extras preference 2621 */ init(WorkbenchWindow w, String layoutID, IAdaptable input, boolean openExtras)2622 private void init(WorkbenchWindow w, String layoutID, IAdaptable input, boolean openExtras) { 2623 // Save args. 2624 this.legacyWindow = w; 2625 this.input = input; 2626 actionSets = new ActionSetManager(w); 2627 initActionSetListener(); 2628 initMaxFileSize(); 2629 } 2630 initMaxFileSize()2631 private void initMaxFileSize() { 2632 IPreferenceStore preferenceStore = PrefUtil.getInternalPreferenceStore(); 2633 maxFileSize = preferenceStore.getLong(IPreferenceConstants.LARGE_DOC_SIZE_FOR_EDITORS); 2634 checkDocumentSize = maxFileSize != 0; 2635 } 2636 2637 @PostConstruct setup(MApplication application, EModelService modelService, IEventBroker broker, MWindow window, EPartService partService)2638 public void setup(MApplication application, EModelService modelService, IEventBroker broker, MWindow window, 2639 EPartService partService) { 2640 this.application = application; 2641 this.modelService = modelService; 2642 this.broker = broker; 2643 this.window = window; 2644 this.partService = partService; 2645 selectionService = ContextInjectionFactory.make(SelectionService.class, window.getContext()); 2646 2647 partService.addPartListener(e4PartListener); 2648 2649 // create editor references for all editors 2650 List<MPart> editors = modelService.findElements(window, CompatibilityEditor.MODEL_ELEMENT_ID, MPart.class, null, 2651 EModelService.IN_ANY_PERSPECTIVE | EModelService.OUTSIDE_PERSPECTIVE | EModelService.IN_SHARED_AREA); 2652 for (MPart editor : editors) { 2653 createEditorReferenceForPart(editor, null, editor.getElementId(), null); 2654 } 2655 2656 // create view references for rendered view placeholders 2657 List<MPlaceholder> placeholders = modelService.findElements(window, null, MPlaceholder.class, null, 2658 EModelService.IN_ANY_PERSPECTIVE | EModelService.OUTSIDE_PERSPECTIVE); 2659 for (MPlaceholder placeholder : placeholders) { 2660 if (placeholder.isToBeRendered()) { 2661 MUIElement ref = placeholder.getRef(); 2662 if (ref instanceof MPart) { 2663 MPart part = (MPart) ref; 2664 String uri = part.getContributionURI(); 2665 if (uri.equals(CompatibilityPart.COMPATIBILITY_VIEW_URI)) { 2666 createViewReferenceForPart(part, part.getElementId()); 2667 } 2668 } 2669 } 2670 } 2671 2672 broker.subscribe(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT, selectionHandler); 2673 broker.subscribe(UIEvents.UIElement.TOPIC_WIDGET, widgetHandler); 2674 broker.subscribe(UIEvents.UIElement.TOPIC_TOBERENDERED, referenceRemovalEventHandler); 2675 broker.subscribe(UIEvents.Contribution.TOPIC_OBJECT, firingHandler); 2676 broker.subscribe(UIEvents.ElementContainer.TOPIC_CHILDREN, childrenHandler); 2677 2678 // Bug 479126 PERSPECTIVE_BAR_EXTRAS setting not taken into account 2679 createPerspectiveBarExtras(); 2680 2681 MPerspectiveStack perspectiveStack = getPerspectiveStack(); 2682 if (perspectiveStack != null) { 2683 extendPerspectives(perspectiveStack); 2684 } 2685 2686 IPerspectiveRegistry registry = getWorkbenchWindow().getWorkbench().getPerspectiveRegistry(); 2687 for (MPerspective perspective : perspectiveStack.getChildren()) { 2688 IPerspectiveDescriptor desc = registry.findPerspectiveWithId(perspective.getElementId()); 2689 if (desc != null) { 2690 sortedPerspectives.add(desc); 2691 } 2692 } 2693 2694 MPerspective selectedPerspective = perspectiveStack.getSelectedElement(); 2695 if (selectedPerspective != null) { 2696 IPerspectiveDescriptor desc = registry.findPerspectiveWithId(selectedPerspective.getElementId()); 2697 if (desc != null) { 2698 sortedPerspectives.remove(desc); 2699 sortedPerspectives.add(desc); 2700 } 2701 } 2702 restoreWorkingSets(); 2703 restoreShowInMruPartIdsList(); 2704 configureExistingWindows(); 2705 } 2706 2707 /* 2708 * Perform any configuration required for an existing MWindow. The association 2709 * of an MWindow to the WorkbenchWindow/WorkbenchPage can occur at different 2710 * times (see Bug 454056 for details). 2711 */ configureExistingWindows()2712 private void configureExistingWindows() { 2713 List<MArea> elements = modelService.findElements(window, null, MArea.class); 2714 for (MArea area : elements) { 2715 Object widget = area.getWidget(); 2716 if (widget instanceof Control) { 2717 installAreaDropSupport((Control) widget); 2718 } 2719 } 2720 } 2721 restoreWorkingSets()2722 public void restoreWorkingSets() { 2723 String workingSetName = getWindowModel().getPersistedState().get(IWorkbenchConstants.TAG_WORKING_SET); 2724 if (workingSetName != null) { 2725 AbstractWorkingSetManager workingSetManager = (AbstractWorkingSetManager) getWorkbenchWindow() 2726 .getWorkbench().getWorkingSetManager(); 2727 setWorkingSet(workingSetManager.getWorkingSet(workingSetName)); 2728 } 2729 2730 String workingSetMemString = getWindowModel().getPersistedState().get(IWorkbenchConstants.TAG_WORKING_SETS); 2731 if (workingSetMemString != null) { 2732 IMemento workingSetMem; 2733 try { 2734 workingSetMem = XMLMemento.createReadRoot(new StringReader(workingSetMemString)); 2735 IMemento[] workingSetChildren = workingSetMem.getChildren(IWorkbenchConstants.TAG_WORKING_SET); 2736 List<IWorkingSet> workingSetList = new ArrayList<>(workingSetChildren.length); 2737 for (IMemento memento : workingSetChildren) { 2738 IWorkingSet set = getWorkbenchWindow().getWorkbench().getWorkingSetManager() 2739 .getWorkingSet(memento.getID()); 2740 if (set != null) { 2741 workingSetList.add(set); 2742 } 2743 } 2744 2745 workingSets = workingSetList.toArray(new IWorkingSet[workingSetList.size()]); 2746 } catch (WorkbenchException e) { 2747 StatusManager.getManager().handle(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.ERROR, 2748 WorkbenchMessages.WorkbenchPage_problemRestoringTitle, e)); 2749 } 2750 } 2751 2752 aggregateWorkingSetId = getWindowModel().getPersistedState().get(ATT_AGGREGATE_WORKING_SET_ID); 2753 } 2754 restoreShowInMruPartIdsList()2755 private void restoreShowInMruPartIdsList() { 2756 String mruList = getWindowModel().getPersistedState().get(IWorkbenchConstants.TAG_SHOW_IN_TIME); 2757 if (mruList != null) { 2758 try { 2759 IMemento memento = XMLMemento.createReadRoot(new StringReader(mruList)); 2760 IMemento[] mementoChildren = memento.getChildren(); 2761 for (IMemento child : mementoChildren) { 2762 mruShowInPartIds.add(child.getID()); 2763 } 2764 } catch (WorkbenchException e) { 2765 StatusManager.getManager().handle(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.ERROR, 2766 WorkbenchMessages.WorkbenchPage_problemRestoringTitle, e)); 2767 } 2768 } 2769 } 2770 2771 @PreDestroy saveWorkingSets()2772 public void saveWorkingSets() { 2773 // Save working set if set 2774 if (workingSet != null) { 2775 getWindowModel().getPersistedState().put(IWorkbenchConstants.TAG_WORKING_SET, workingSet.getName()); 2776 } else { 2777 getWindowModel().getPersistedState().remove(IWorkbenchConstants.TAG_WORKING_SET); 2778 } 2779 2780 List<String> workingSetNames = new ArrayList<>(workingSets.length); 2781 for (IWorkingSet workingSet : workingSets) { 2782 workingSetNames.add(workingSet.getName()); 2783 } 2784 saveMemento(IWorkbenchConstants.TAG_WORKING_SETS, IWorkbenchConstants.TAG_WORKING_SET, workingSetNames); 2785 2786 getWindowModel().getPersistedState().put(ATT_AGGREGATE_WORKING_SET_ID, aggregateWorkingSetId); 2787 } 2788 2789 @PreDestroy saveShowInMruPartIdsList()2790 public void saveShowInMruPartIdsList() { 2791 saveMemento(IWorkbenchConstants.TAG_SHOW_IN_TIME, IWorkbenchConstants.TAG_ID, mruShowInPartIds); 2792 } 2793 saveMemento(String rootType, String childType, Collection<String> ids)2794 private void saveMemento(String rootType, String childType, Collection<String> ids) { 2795 XMLMemento memento = XMLMemento.createWriteRoot(rootType); 2796 for (String id : ids) { 2797 memento.createChild(childType, id); 2798 } 2799 StringWriter writer = new StringWriter(); 2800 try { 2801 memento.save(writer); 2802 getWindowModel().getPersistedState().put(rootType, writer.getBuffer().toString()); 2803 } catch (IOException e) { 2804 // Simply don't store the settings 2805 StatusManager.getManager().handle( 2806 new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.ERROR, WorkbenchMessages.SavingProblem, e)); 2807 } 2808 } 2809 2810 /** 2811 * Extends the perspectives within the given stack with action set contributions 2812 * from the <code>perspectiveExtensions</code> extension point. 2813 * 2814 * @param perspectiveStack the stack that contain the perspectives to be 2815 * extended 2816 */ extendPerspectives(MPerspectiveStack perspectiveStack)2817 private void extendPerspectives(MPerspectiveStack perspectiveStack) { 2818 for (MPerspective perspective : perspectiveStack.getChildren()) { 2819 String id = perspective.getElementId(); 2820 IPerspectiveDescriptor desc = getWorkbenchWindow().getWorkbench().getPerspectiveRegistry() 2821 .findPerspectiveWithId(id); 2822 if (desc != null) { 2823 MPerspective temporary = modelService.createModelElement(MPerspective.class); 2824 ModeledPageLayout modelLayout = new ModeledPageLayout(window, modelService, partService, temporary, 2825 desc, this, true); 2826 2827 PerspectiveExtensionReader reader = new PerspectiveExtensionReader(); 2828 reader.setIncludeOnlyTags(new String[] { IWorkbenchRegistryConstants.TAG_ACTION_SET }); 2829 reader.extendLayout(null, id, modelLayout); 2830 2831 addActionSet(perspective, temporary); 2832 } 2833 } 2834 } 2835 getPerspectiveExtensionActionSets(String id)2836 ArrayList<String> getPerspectiveExtensionActionSets(String id) { 2837 IPerspectiveDescriptor desc = getWorkbenchWindow().getWorkbench().getPerspectiveRegistry() 2838 .findPerspectiveWithId(id); 2839 if (desc != null) { 2840 MPerspective temporary = modelService.createModelElement(MPerspective.class); 2841 ModeledPageLayout modelLayout = new ModeledPageLayout(window, modelService, partService, temporary, desc, 2842 this, true); 2843 2844 PerspectiveExtensionReader reader = new PerspectiveExtensionReader(); 2845 reader.setIncludeOnlyTags(new String[] { IWorkbenchRegistryConstants.TAG_ACTION_SET }); 2846 reader.extendLayout(null, id, modelLayout); 2847 return new ArrayList<>(ModeledPageLayout.getIds(temporary, ModeledPageLayout.ACTION_SET_TAG)); 2848 } 2849 return null; 2850 } 2851 2852 /** 2853 * Copies action set extensions from the temporary perspective to the other one. 2854 * 2855 * @param perspective the perspective to copy action set contributions to 2856 * @param temporary the perspective to copy action set contributions from 2857 */ addActionSet(MPerspective perspective, MPerspective temporary)2858 private void addActionSet(MPerspective perspective, MPerspective temporary) { 2859 List<String> tags = perspective.getTags(); 2860 List<String> extendedTags = temporary.getTags(); 2861 for (String extendedTag : extendedTags) { 2862 if (!tags.contains(extendedTag)) { 2863 tags.add(extendedTag); 2864 } 2865 } 2866 } 2867 2868 /** 2869 * Installs drop support into the shared area so that editors can be opened by 2870 * dragging and dropping files into it. 2871 * 2872 * @param control the control to attach the drop support to 2873 */ installAreaDropSupport(Control control)2874 private void installAreaDropSupport(Control control) { 2875 if (!dndSupportInstalled) { 2876 WorkbenchWindowConfigurer configurer = legacyWindow.getWindowConfigurer(); 2877 DropTargetListener dropTargetListener = configurer.getDropTargetListener(); 2878 if (dropTargetListener != null) { 2879 DropTarget dropTarget = new DropTarget(control, DND.DROP_DEFAULT | DND.DROP_COPY | DND.DROP_LINK); 2880 dropTarget.setTransfer(configurer.getTransfers()); 2881 dropTarget.addDropListener(dropTargetListener); 2882 } 2883 dndSupportInstalled = true; 2884 } 2885 } 2886 getPartStacks(MPerspective perspective)2887 private List<MPartStack> getPartStacks(MPerspective perspective) { 2888 if (perspective == null) { 2889 return Collections.emptyList(); 2890 } 2891 return modelService.findElements(perspective, null, MPartStack.class); 2892 } 2893 2894 private EventHandler selectionHandler = event -> { 2895 Object changedElement = event.getProperty(UIEvents.EventTags.ELEMENT); 2896 2897 if (!(changedElement instanceof MPerspectiveStack)) { 2898 return; 2899 } 2900 2901 List<MPerspectiveStack> theStack = modelService.findElements(window, null, MPerspectiveStack.class, null); 2902 if (theStack.isEmpty()) { 2903 return; 2904 } else if (!theStack.isEmpty() && changedElement != theStack.get(0)) { 2905 return; 2906 } 2907 2908 MPerspective oldPersp = (MPerspective) event.getProperty(UIEvents.EventTags.OLD_VALUE); 2909 MPerspective newPersp = (MPerspective) event.getProperty(UIEvents.EventTags.NEW_VALUE); 2910 // updatePerspectiveActionSets(oldPersp, newPersp); 2911 2912 // ((CoolBarToTrimManager) 2913 // legacyWindow.getCoolBarManager2()).updateAll(true); 2914 // legacyWindow.menuManager.updateAll(true); 2915 2916 List<MPart> hiddenParts = new ArrayList<>(); 2917 List<MPart> visibleParts = new ArrayList<>(); 2918 2919 List<MPartStack> oldStacks = getPartStacks(oldPersp); 2920 List<MPartStack> newStacks = getPartStacks(newPersp); 2921 2922 for (MPartStack oldStack : oldStacks) { 2923 MStackElement element1 = oldStack.getSelectedElement(); 2924 if (element1 instanceof MPlaceholder) { 2925 hiddenParts.add((MPart) ((MPlaceholder) element1).getRef()); 2926 } else if (element1 instanceof MPart) { 2927 hiddenParts.add((MPart) element1); 2928 } 2929 } 2930 2931 for (MPartStack newStack : newStacks) { 2932 MStackElement element2 = newStack.getSelectedElement(); 2933 if (element2 instanceof MPlaceholder) { 2934 visibleParts.add((MPart) ((MPlaceholder) element2).getRef()); 2935 } else if (element2 instanceof MPart) { 2936 visibleParts.add((MPart) element2); 2937 } 2938 } 2939 2940 List<MPart> ignoredParts = new ArrayList<>(); 2941 for (MPart hiddenPart1 : hiddenParts) { 2942 if (visibleParts.contains(hiddenPart1)) { 2943 ignoredParts.add(hiddenPart1); 2944 } 2945 } 2946 2947 hiddenParts.removeAll(ignoredParts); 2948 visibleParts.removeAll(ignoredParts); 2949 2950 for (MPart hiddenPart2 : hiddenParts) { 2951 firePartHidden(hiddenPart2); 2952 } 2953 2954 for (MPart visiblePart : visibleParts) { 2955 firePartVisible(visiblePart); 2956 } 2957 2958 updateActionSets(getPerspective(oldPersp), getPerspective(newPersp)); 2959 2960 // might've been set to null if we were closing the perspective 2961 if (newPersp != null) { 2962 IPerspectiveDescriptor perspective = getPerspectiveDesc(newPersp.getElementId()); 2963 legacyWindow.firePerspectiveActivated(WorkbenchPage.this, perspective); 2964 2965 sortedPerspectives.remove(perspective); 2966 sortedPerspectives.add(perspective); 2967 } 2968 legacyWindow.updateActionSets(); 2969 }; 2970 2971 /** 2972 * See IWorkbenchPage. 2973 */ 2974 @Override isPartVisible(IWorkbenchPart part)2975 public boolean isPartVisible(IWorkbenchPart part) { 2976 MPart mpart = findPart(part); 2977 return mpart == null ? false : partService.isPartVisible(mpart); 2978 } 2979 findSharedArea()2980 public MUIElement findSharedArea() { 2981 MPerspective perspective = getPerspectiveStack().getSelectedElement(); 2982 return perspective == null ? null : modelService.find(IPageLayout.ID_EDITOR_AREA, perspective); 2983 } 2984 2985 /** 2986 * See IWorkbenchPage. 2987 */ 2988 @Override isEditorAreaVisible()2989 public boolean isEditorAreaVisible() { 2990 MUIElement find = findSharedArea(); 2991 return find == null ? false : find.isVisible() && find.isToBeRendered(); 2992 } 2993 2994 @Override isPageZoomed()2995 public boolean isPageZoomed() { 2996 List<String> maxTag = new ArrayList<>(); 2997 maxTag.add(IPresentationEngine.MAXIMIZED); 2998 List<Object> maxElements = modelService.findElements(window, null, null, maxTag); 2999 return maxElements.size() > 0; 3000 } 3001 3002 // /** 3003 // * This method is called when the page is activated. 3004 // */ 3005 // protected void onActivate() { 3006 // composite.setVisible(true); 3007 // Perspective persp = getActivePerspective(); 3008 // 3009 // if (persp != null) { 3010 // persp.onActivate(); 3011 // updateVisibility(null, persp); 3012 // } 3013 // } 3014 // 3015 // /** 3016 // * This method is called when the page is deactivated. 3017 // */ 3018 // protected void onDeactivate() { 3019 // makeActiveEditor(null); 3020 // makeActive(null); 3021 // if (getActivePerspective() != null) { 3022 // getActivePerspective().onDeactivate(); 3023 // } 3024 // composite.setVisible(false); 3025 // } 3026 3027 /** 3028 * See IWorkbenchPage. 3029 */ 3030 @Override reuseEditor(IReusableEditor editor, IEditorInput input)3031 public void reuseEditor(IReusableEditor editor, IEditorInput input) { 3032 3033 // Rather than calling editor.setInput on the editor directly, we do it through 3034 // the part reference. 3035 // This case lets us detect badly behaved editors that are not firing a 3036 // PROP_INPUT event in response 3037 // to the input change... but if all editors obeyed their API contract, the 3038 // "else" branch would be 3039 // sufficient. 3040 3041 // TODO compat: should we be talking to the editor reference here 3042 editor.setInput(input); 3043 navigationHistory.markEditor(editor); 3044 } 3045 3046 /** 3047 * See IWorkbenchPage. 3048 */ 3049 @Override openEditor(IEditorInput input, String editorID)3050 public IEditorPart openEditor(IEditorInput input, String editorID) throws PartInitException { 3051 return openEditor(input, editorID, true, MATCH_INPUT); 3052 } 3053 3054 /** 3055 * See IWorkbenchPage. 3056 */ 3057 @Override openEditor(IEditorInput input, String editorID, boolean activate)3058 public IEditorPart openEditor(IEditorInput input, String editorID, boolean activate) throws PartInitException { 3059 return openEditor(input, editorID, activate, MATCH_INPUT); 3060 } 3061 3062 /** 3063 * See IWorkbenchPage. 3064 */ 3065 @Override openEditor(final IEditorInput input, final String editorID, final boolean activate, final int matchFlags)3066 public IEditorPart openEditor(final IEditorInput input, final String editorID, final boolean activate, 3067 final int matchFlags) throws PartInitException { 3068 return openEditor(input, editorID, activate, matchFlags, null, true); 3069 } 3070 3071 /** 3072 * This is not public API but for use internally. editorState can be 3073 * <code>null</code>. 3074 * 3075 * @param input the input to open the editor with 3076 * @param editorID the id of the editor to open 3077 * @param activate <code>true</code> if the editor should be activated, 3078 * <code>false</code> otherwise 3079 * @param matchFlags a bit mask consisting of zero or more of the MATCH_* 3080 * constants OR-ed together 3081 * @param editorState the previously saved state of the editor as a memento, 3082 * this may be <code>null</code> 3083 * @param notify <code>true</code> if the perspective should fire off 3084 * events about the editors being opened, <code>false</code> 3085 * otherwise 3086 * @return the opened editor 3087 * @exception PartInitException if the editor could not be created or 3088 * initialized 3089 */ openEditor(final IEditorInput input, final String editorID, final boolean activate, final int matchFlags, final IMemento editorState, final boolean notify)3090 public IEditorPart openEditor(final IEditorInput input, final String editorID, final boolean activate, 3091 final int matchFlags, final IMemento editorState, final boolean notify) throws PartInitException { 3092 if (input == null || editorID == null) { 3093 throw new IllegalArgumentException(); 3094 } 3095 3096 final IEditorPart result[] = new IEditorPart[1]; 3097 final PartInitException ex[] = new PartInitException[1]; 3098 BusyIndicator.showWhile(legacyWindow.getWorkbench().getDisplay(), () -> { 3099 try { 3100 result[0] = busyOpenEditor(input, editorID, activate, matchFlags, editorState, notify); 3101 } catch (PartInitException e) { 3102 ex[0] = e; 3103 } 3104 }); 3105 if (ex[0] != null) { 3106 throw ex[0]; 3107 } 3108 return result[0]; 3109 } 3110 3111 /** 3112 * @see #openEditor(IEditorInput, String, boolean, int) 3113 */ busyOpenEditor(IEditorInput input, String editorId, boolean activate, int matchFlags, IMemento editorState, boolean notify)3114 private IEditorPart busyOpenEditor(IEditorInput input, String editorId, boolean activate, int matchFlags, 3115 IMemento editorState, boolean notify) throws PartInitException { 3116 3117 if (input == null || editorId == null) { 3118 throw new IllegalArgumentException(); 3119 } 3120 3121 // Special handling for external editors (they have no tabs...) 3122 if (IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID.equals(editorId)) { 3123 IPathEditorInput fileInput = getPathEditorInput(input); 3124 if (fileInput == null) { 3125 throw new PartInitException(WorkbenchMessages.EditorManager_systemEditorError); 3126 } 3127 3128 String fullPath = fileInput.getPath().toOSString(); 3129 Program.launch(fullPath); 3130 return null; 3131 } 3132 3133 IEditorDescriptor desc = getWorkbenchWindow().getWorkbench().getEditorRegistry().findEditor(editorId); 3134 if (desc != null && !desc.isOpenExternal() && isLargeDocument(input)) { 3135 desc = getAlternateEditor(); 3136 if (desc == null) { 3137 // the user pressed cancel in the editor selection dialog 3138 return null; 3139 } 3140 } 3141 if (desc == null) { 3142 throw new PartInitException(NLS.bind(WorkbenchMessages.EditorManager_unknownEditorIDMessage, editorId)); 3143 } 3144 3145 setEditorAreaVisible(true); 3146 3147 IEditorReference[] editorReferences = findEditors(input, editorId, matchFlags); 3148 if (editorReferences.length != 0) { 3149 IEditorPart editor = editorReferences[0].getEditor(true); 3150 if (editor instanceof IShowEditorInput) { 3151 ((IShowEditorInput) editor).showEditorInput(input); 3152 } 3153 3154 partService.showPart(((EditorReference) editorReferences[0]).getModel(), PartState.VISIBLE); 3155 3156 if (activate) { 3157 activate(editor); 3158 } 3159 3160 recordEditor(input, desc); 3161 return editor; 3162 } else if (desc.isInternal()) { 3163 // look for an editor to reuse 3164 EditorReference reusableEditorRef = (EditorReference) ((TabBehaviour) Tweaklets.get(TabBehaviour.KEY)) 3165 .findReusableEditor(this); 3166 if (reusableEditorRef != null) { 3167 IEditorPart reusableEditor = reusableEditorRef.getEditor(false); 3168 if (editorId.equals(reusableEditorRef.getId()) && reusableEditor instanceof IReusableEditor) { 3169 // reusable editors that share the same id are okay 3170 recordEditor(input, desc); 3171 reuseEditor((IReusableEditor) reusableEditor, input); 3172 3173 MPart editor = reusableEditorRef.getModel(); 3174 partService.showPart(editor, PartState.VISIBLE); 3175 if (activate) { 3176 partService.activate(editor); 3177 } else { 3178 updateActiveEditorSources(editor); 3179 } 3180 return reusableEditor; 3181 } 3182 // should have saved already if necessary, close this editor, a 3183 // new one will be opened 3184 closeEditor(reusableEditorRef, false); 3185 } 3186 } else if (desc.isOpenExternal()) { 3187 openExternalEditor((EditorDescriptor) desc, input); 3188 // no editor parts for external editors, return null 3189 return null; 3190 } 3191 3192 MPart editor = partService.createPart(CompatibilityEditor.MODEL_ELEMENT_ID); 3193 editor.getTags().add(editorId); 3194 EditorReference ref = createEditorReferenceForPart(editor, input, editorId, editorState); 3195 partService.showPart(editor, PartState.VISIBLE); 3196 3197 CompatibilityEditor compatibilityEditor = (CompatibilityEditor) editor.getObject(); 3198 if (compatibilityEditor == null) { 3199 return null; 3200 } 3201 3202 if (activate) { 3203 partService.activate(editor); 3204 } else { 3205 updateActiveEditorSources(editor); 3206 } 3207 3208 if (notify) { 3209 legacyWindow.firePerspectiveChanged(this, getPerspective(), ref, CHANGE_EDITOR_OPEN); 3210 legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_EDITOR_OPEN); 3211 } 3212 3213 recordEditor(input, desc); 3214 return compatibilityEditor.getEditor(); 3215 } 3216 recordEditor(IEditorInput input, IEditorDescriptor descriptor)3217 private void recordEditor(IEditorInput input, IEditorDescriptor descriptor) { 3218 EditorHistory history = ((Workbench) legacyWindow.getWorkbench()).getEditorHistory(); 3219 history.add(input, descriptor); 3220 } 3221 getAlternateEditor()3222 private static IEditorDescriptor getAlternateEditor() { 3223 Shell shell = ProgressManagerUtil.getDefaultParent(); 3224 EditorSelectionDialog dialog = new EditorSelectionDialog(shell) { 3225 @Override 3226 protected IDialogSettings getDialogSettings() { 3227 IDialogSettings result = new DialogSettings("EditorSelectionDialog"); //$NON-NLS-1$ 3228 result.put(EditorSelectionDialog.STORE_ID_INTERNAL_EXTERNAL, true); 3229 return result; 3230 } 3231 }; 3232 dialog.setMessage(WorkbenchMessages.EditorManager_largeDocumentWarning); 3233 3234 if (dialog.open() == Window.OK) 3235 return dialog.getSelectedEditor(); 3236 return null; 3237 } 3238 isLargeDocument(IEditorInput editorInput)3239 boolean isLargeDocument(IEditorInput editorInput) { 3240 3241 if (!checkDocumentSize) 3242 return false; 3243 3244 if (!(editorInput instanceof IPathEditorInput)) 3245 return false; // we know nothing about it 3246 3247 try { 3248 IPath path = ((IPathEditorInput) editorInput).getPath(); 3249 File file = new File(path.toOSString()); 3250 return file.length() > maxFileSize; 3251 } catch (Exception e) { 3252 // ignore exceptions 3253 return false; 3254 } 3255 } 3256 3257 /** 3258 * See IWorkbenchPage. 3259 */ 3260 @Override isEditorPinned(IEditorPart editor)3261 public boolean isEditorPinned(IEditorPart editor) { 3262 WorkbenchPartReference ref = (WorkbenchPartReference) getReference(editor); 3263 return ref != null && ref.isPinned(); 3264 } 3265 3266 /** 3267 * Removes an IPartListener from the part service. 3268 */ 3269 @Override removePartListener(IPartListener l)3270 public void removePartListener(IPartListener l) { 3271 partListenerList.remove(l); 3272 } 3273 3274 /** 3275 * Removes an IPartListener from the part service. 3276 */ 3277 @Override removePartListener(IPartListener2 l)3278 public void removePartListener(IPartListener2 l) { 3279 partListener2List.remove(l); 3280 } 3281 3282 /** 3283 * Implements IWorkbenchPage 3284 * 3285 * @see org.eclipse.ui.IWorkbenchPage#removePropertyChangeListener(IPropertyChangeListener) 3286 * @since 2.0 3287 * @deprecated individual views should store a working set if needed and 3288 * register a property change listener directly with the working set 3289 * manager to receive notification when the view working set is 3290 * removed. 3291 */ 3292 @Deprecated 3293 @Override removePropertyChangeListener(IPropertyChangeListener listener)3294 public void removePropertyChangeListener(IPropertyChangeListener listener) { 3295 propertyChangeListeners.remove(listener); 3296 } 3297 3298 @Override removeSelectionListener(ISelectionListener listener)3299 public void removeSelectionListener(ISelectionListener listener) { 3300 selectionService.removeSelectionListener(listener); 3301 } 3302 3303 @Override removeSelectionListener(String partId, ISelectionListener listener)3304 public void removeSelectionListener(String partId, ISelectionListener listener) { 3305 selectionService.removeSelectionListener(partId, listener); 3306 } 3307 3308 @Override removePostSelectionListener(ISelectionListener listener)3309 public void removePostSelectionListener(ISelectionListener listener) { 3310 selectionService.removePostSelectionListener(listener); 3311 } 3312 3313 @Override removePostSelectionListener(String partId, ISelectionListener listener)3314 public void removePostSelectionListener(String partId, ISelectionListener listener) { 3315 selectionService.removePostSelectionListener(partId, listener); 3316 } 3317 3318 /** 3319 * Resets the layout for the perspective. The active part in the old layout is 3320 * activated in the new layout for consistent user context. 3321 */ 3322 @Override resetPerspective()3323 public void resetPerspective() { 3324 MPerspectiveStack perspStack = getPerspectiveStack(); 3325 MPerspective persp = perspStack.getSelectedElement(); 3326 if (persp == null) 3327 return; 3328 3329 // HACK!! the 'perspective' field doesn't match reality... 3330 IPerspectiveDescriptor desc = PlatformUI.getWorkbench().getPerspectiveRegistry() 3331 .findPerspectiveWithId(persp.getElementId()); 3332 if (desc == null) 3333 return; 3334 3335 // send out reset notification 3336 legacyWindow.firePerspectiveChanged(this, desc, CHANGE_RESET); 3337 3338 // collect all the parts under the current perspective 3339 List<MPart> perspectiveParts = modelService.findElements(persp, null, MPart.class, null); 3340 // find the shared area 3341 MUIElement area = findSharedArea(); 3342 if (area != null) { 3343 // remove all editors in the shared area from the list of parts 3344 perspectiveParts.removeAll( 3345 modelService.findElements(area, CompatibilityEditor.MODEL_ELEMENT_ID, MPart.class, null)); 3346 } 3347 3348 List<MPart> dirtyParts = new ArrayList<>(); 3349 List<IWorkbenchPart> partsToSave = new ArrayList<>(); 3350 // iterate over the list of parts to find dirty parts 3351 for (MPart currentPart : perspectiveParts) { 3352 if (currentPart.isDirty()) { 3353 Object object = currentPart.getObject(); 3354 if (object == null) { 3355 continue; 3356 } else if (object instanceof CompatibilityPart) { 3357 IWorkbenchPart workbenchPart = getWrappedPart((CompatibilityPart) object); 3358 if (workbenchPart == null) { 3359 continue; 3360 } 3361 ISaveablePart saveable = SaveableHelper.getSaveable(workbenchPart); 3362 if (saveable == null || !saveable.isSaveOnCloseNeeded()) { 3363 continue; 3364 } 3365 partsToSave.add(workbenchPart); 3366 } 3367 3368 dirtyParts.add(currentPart); 3369 } 3370 } 3371 3372 SaveablesList saveablesList = null; 3373 Object postCloseInfo = null; 3374 if (partsToSave.size() > 0) { 3375 saveablesList = (SaveablesList) getWorkbenchWindow().getService(ISaveablesLifecycleListener.class); 3376 postCloseInfo = saveablesList.preCloseParts(partsToSave, true, this.getWorkbenchWindow()); 3377 if (postCloseInfo == null) { 3378 // cancel 3379 // We're not going through with the reset, so it is 3380 // complete. 3381 legacyWindow.firePerspectiveChanged(this, desc, CHANGE_RESET_COMPLETE); 3382 return; 3383 } 3384 } 3385 3386 modelService.resetPerspectiveModel(persp, window); 3387 3388 if (saveablesList != null) { 3389 saveablesList.postClose(postCloseInfo); 3390 } 3391 3392 boolean revert = false; 3393 if (desc instanceof PerspectiveDescriptor) { 3394 PerspectiveDescriptor perspectiveDescriptor = (PerspectiveDescriptor) desc; 3395 revert = perspectiveDescriptor.isPredefined() && !perspectiveDescriptor.hasCustomDefinition(); 3396 } 3397 3398 MPerspective dummyPerspective = null; 3399 if (!revert) { 3400 dummyPerspective = (MPerspective) modelService.cloneSnippet(application, desc.getId(), window); 3401 if (dummyPerspective != null) { 3402 handleNullRefPlaceHolders(dummyPerspective, window); 3403 } 3404 } 3405 3406 if (dummyPerspective == null) { 3407 // instantiate a dummy perspective perspective 3408 dummyPerspective = modelService.createModelElement(MPerspective.class); 3409 dummyPerspective.setElementId(persp.getElementId()); 3410 3411 IPerspectiveFactory factory = ((PerspectiveDescriptor) desc).createFactory(); 3412 ModeledPageLayout modelLayout = new ModeledPageLayout(window, modelService, partService, dummyPerspective, 3413 desc, this, true); 3414 factory.createInitialLayout(modelLayout); 3415 3416 PerspectiveTagger.tagPerspective(dummyPerspective, modelService); 3417 PerspectiveExtensionReader reader = new PerspectiveExtensionReader(); 3418 reader.extendLayout(getExtensionTracker(), desc.getId(), modelLayout); 3419 } 3420 3421 String hiddenItems = dummyPerspective.getPersistedState().get(ModeledPageLayout.HIDDEN_ITEMS_KEY); 3422 persp.getPersistedState().put(ModeledPageLayout.HIDDEN_ITEMS_KEY, hiddenItems); 3423 3424 legacyWindow.getMenuManager().updateAll(true); 3425 // ((ICoolBarManager2) ((WorkbenchWindow) 3426 // getWorkbenchWindow()).getCoolBarManager2()) 3427 // .resetItemOrder(); 3428 3429 // Hide placeholders for parts that exist in the 'global' areas 3430 modelService.hideLocalPlaceholders(window, dummyPerspective); 3431 3432 int dCount = dummyPerspective.getChildren().size(); 3433 while (dummyPerspective.getChildren().size() > 0) { 3434 MPartSashContainerElement dChild = dummyPerspective.getChildren().remove(0); 3435 persp.getChildren().add(dChild); 3436 } 3437 3438 while (persp.getChildren().size() > dCount) { 3439 MUIElement child = persp.getChildren().get(0); 3440 child.setToBeRendered(false); 3441 persp.getChildren().remove(0); 3442 } 3443 3444 List<MWindow> existingDetachedWindows = new ArrayList<>(); 3445 existingDetachedWindows.addAll(persp.getWindows()); 3446 3447 // Move any detached windows from template to perspective 3448 while (dummyPerspective.getWindows().size() > 0) { 3449 MWindow detachedWindow = dummyPerspective.getWindows().remove(0); 3450 persp.getWindows().add(detachedWindow); 3451 } 3452 3453 // Remove original windows. Can't remove them first or the MParts will be 3454 // disposed 3455 for (MWindow detachedWindow : existingDetachedWindows) { 3456 detachedWindow.setToBeRendered(false); 3457 persp.getWindows().remove(detachedWindow); 3458 } 3459 3460 // deactivate and activate other action sets as 3461 Perspective oldPersp = getPerspective(persp); 3462 Perspective dummyPersp = getPerspective(dummyPerspective); 3463 updateActionSets(oldPersp, dummyPersp); 3464 oldPersp.getAlwaysOnActionSets().clear(); 3465 oldPersp.getAlwaysOnActionSets().addAll(dummyPersp.getAlwaysOnActionSets()); 3466 oldPersp.getAlwaysOffActionSets().clear(); 3467 oldPersp.getAlwaysOffActionSets().addAll(dummyPersp.getAlwaysOffActionSets()); 3468 3469 modelToPerspectiveMapping.remove(dummyPerspective); 3470 3471 // partly fixing toolbar refresh issue, see bug 383569 comment 10 3472 legacyWindow.updateActionSets(); 3473 3474 // migrate the tags 3475 List<String> tags = persp.getTags(); 3476 tags.clear(); 3477 tags.addAll(dummyPerspective.getTags()); 3478 3479 // remove HIDDEN_EXPLICITLY tag from trim elements 3480 List<MTrimElement> trimElements = modelService.findElements(window, null, MTrimElement.class, null); 3481 for (MTrimElement mTrimElement : trimElements) { 3482 mTrimElement.getTags().remove(IPresentationEngine.HIDDEN_EXPLICITLY); 3483 } 3484 3485 partService.requestActivation(); 3486 3487 // reset complete 3488 legacyWindow.firePerspectiveChanged(this, desc, CHANGE_RESET_COMPLETE); 3489 UIEvents.publishEvent(UIEvents.UILifeCycle.PERSPECTIVE_RESET, persp); 3490 } 3491 initActionSetListener()3492 private void initActionSetListener() { 3493 // actionSets.addListener(new IPropertyListener() { 3494 // public void propertyChanged(Object source, int propId) { 3495 // if (source instanceof IActionSetDescriptor) { 3496 // final IActionSetDescriptor desc = (IActionSetDescriptor) source; 3497 // final String actionSetId = ModeledPageLayout.ACTION_SET_TAG + 3498 // desc.getId(); 3499 // final MPerspective currentPerspective = getCurrentPerspective(); 3500 // if (currentPerspective != null) { 3501 // final List<String> tags = currentPerspective.getTags(); 3502 // if (propId == ActionSetManager.PROP_VISIBLE) { 3503 // if (!tags.contains(actionSetId)) { 3504 // tags.add(actionSetId); 3505 // } 3506 // } else if (propId == ActionSetManager.PROP_HIDDEN) { 3507 // tags.remove(actionSetId); 3508 // } 3509 // } 3510 // } 3511 // } 3512 // }); 3513 } 3514 3515 /** 3516 * See IWorkbenchPage 3517 */ 3518 @Override saveAllEditors(boolean confirm)3519 public boolean saveAllEditors(boolean confirm) { 3520 return saveAllEditors(confirm, false, false); 3521 } 3522 3523 /** 3524 * @return {@link ISaveablePart} objects derived from {@link IWorkbenchPart} 's 3525 * on this page 3526 */ getDirtyParts()3527 public ISaveablePart[] getDirtyParts() { 3528 List<ISaveablePart> result = new ArrayList<>(3); 3529 IWorkbenchPartReference[] allParts = getSortedParts(true, true, true); 3530 for (IWorkbenchPartReference reference : allParts) { 3531 IWorkbenchPart part = reference.getPart(false); 3532 ISaveablePart saveable = SaveableHelper.getSaveable(part); 3533 if (saveable != null && !result.contains(saveable)) { 3534 if (saveable.isDirty()) { 3535 result.add(saveable); 3536 } 3537 } 3538 } 3539 return result.toArray(new ISaveablePart[result.size()]); 3540 } 3541 3542 /** 3543 * @return workbench parts which are dirty (implement or adapt to 3544 * {@link ISaveablePart}). Only parts matching different saveables are 3545 * returned. 3546 */ getDirtyWorkbenchParts()3547 public IWorkbenchPart[] getDirtyWorkbenchParts() { 3548 List<IWorkbenchPart> result = new ArrayList<>(3); 3549 Map<ISaveablePart, IWorkbenchPart> saveables = new LinkedHashMap<>(3); 3550 IWorkbenchPartReference[] allParts = getSortedParts(true, true, true); 3551 for (IWorkbenchPartReference reference : allParts) { 3552 IWorkbenchPart part = reference.getPart(false); 3553 ISaveablePart saveable = SaveableHelper.getSaveable(part); 3554 if (saveable == null || !saveable.isDirty()) { 3555 continue; 3556 } 3557 IWorkbenchPart previousPart = saveables.get(saveable); 3558 if (previousPart != null) { 3559 // We have already a part claiming to handle this saveable. 3560 // See bug 470076 where a property view might return 3561 // saveable which is in turn just editor part 3562 if (previousPart == saveable) { 3563 // if the previous part matches saveable, we have a 3564 // perfect match already 3565 continue; 3566 } 3567 // if parts provide adapters to same saveable but 3568 // saveable itself is not a part, we can try to keep 3569 // editors and skip views 3570 if (part != saveable && previousPart instanceof IEditorPart) { 3571 continue; 3572 } 3573 // last part wins, since we don't want to return multiple parts 3574 // representing same saveables 3575 result.remove(previousPart); 3576 } 3577 result.add(part); 3578 saveables.put(saveable, part); 3579 } 3580 return result.toArray(new IWorkbenchPart[result.size()]); 3581 } 3582 saveAllEditors(boolean confirm, boolean closing, boolean addNonPartSources)3583 public boolean saveAllEditors(boolean confirm, boolean closing, boolean addNonPartSources) { 3584 IWorkbenchPart[] parts = getDirtyWorkbenchParts(); 3585 if (parts.length == 0) { 3586 return true; 3587 } 3588 // saveAll below expects a mutable list 3589 List<IWorkbenchPart> dirtyParts = new ArrayList<>(parts.length); 3590 dirtyParts.addAll(Arrays.asList(parts)); 3591 3592 // If confirmation is required .. 3593 return saveAll(dirtyParts, confirm, closing, addNonPartSources, legacyWindow, legacyWindow); 3594 } 3595 saveAll(List<IWorkbenchPart> dirtyParts, final boolean confirm, final boolean closing, boolean addNonPartSources, final IRunnableContext runnableContext, final IWorkbenchWindow workbenchWindow)3596 public static boolean saveAll(List<IWorkbenchPart> dirtyParts, final boolean confirm, final boolean closing, 3597 boolean addNonPartSources, final IRunnableContext runnableContext, final IWorkbenchWindow workbenchWindow) { 3598 // clone the input list 3599 dirtyParts = new ArrayList<>(dirtyParts); 3600 3601 if (closing) { 3602 // if the parts are going to be closed, then we only save those that 3603 // need to be saved when closed, see bug 272070 3604 removeSaveOnCloseNotNeededParts(dirtyParts); 3605 } 3606 3607 SaveablesList saveablesList = (SaveablesList) PlatformUI.getWorkbench() 3608 .getService(ISaveablesLifecycleListener.class); 3609 if (confirm) { 3610 return processSaveable2(dirtyParts) ? false 3611 : saveablesList.preCloseParts(dirtyParts, true, true, workbenchWindow, workbenchWindow) != null; 3612 } 3613 List<Saveable> modelsToSave = convertToSaveables(dirtyParts, closing, addNonPartSources); 3614 return modelsToSave.isEmpty() ? true 3615 : !saveablesList.saveModels(modelsToSave, workbenchWindow, runnableContext, closing); 3616 3617 } 3618 3619 /** 3620 * Removes from the provided list parts that don't need to be saved on close. 3621 * 3622 * @param parts the list of the parts (ISaveablePart) 3623 */ removeSaveOnCloseNotNeededParts(List<IWorkbenchPart> parts)3624 private static void removeSaveOnCloseNotNeededParts(List<IWorkbenchPart> parts) { 3625 for (Iterator<IWorkbenchPart> it = parts.iterator(); it.hasNext();) { 3626 IWorkbenchPart part = it.next(); 3627 ISaveablePart saveable = SaveableHelper.getSaveable(part); 3628 if (saveable == null || !saveable.isSaveOnCloseNeeded()) { 3629 it.remove(); 3630 } 3631 } 3632 } 3633 3634 /** 3635 * Processes all parts that implement ISaveablePart2 and removes them from the 3636 * list. 3637 * 3638 * @param dirtyParts the list of the parts 3639 * @return true if cancelled 3640 */ processSaveable2(List<IWorkbenchPart> dirtyParts)3641 private static boolean processSaveable2(List<IWorkbenchPart> dirtyParts) { 3642 boolean saveable2Processed = false; 3643 // Process all parts that implement ISaveablePart2. 3644 // These parts are removed from the list after saving 3645 // them. We then need to restore the workbench to 3646 // its previous state, for now this is just last 3647 // active perspective. 3648 // Note that the given parts may come from multiple 3649 // windows, pages and perspectives. 3650 ListIterator<IWorkbenchPart> listIterator = dirtyParts.listIterator(); 3651 3652 WorkbenchPage currentPage = null; 3653 Perspective currentPageOriginalPerspective = null; 3654 while (listIterator.hasNext()) { 3655 IWorkbenchPart part = listIterator.next(); 3656 ISaveablePart2 saveable2 = SaveableHelper.getSaveable2(part); 3657 if (saveable2 != null) { 3658 WorkbenchPage page = (WorkbenchPage) part.getSite().getPage(); 3659 if (!Objects.equals(currentPage, page)) { 3660 if (currentPage != null && currentPageOriginalPerspective != null) { 3661 if (!currentPageOriginalPerspective.equals(currentPage.getActivePerspective())) { 3662 currentPage.setPerspective(currentPageOriginalPerspective.getDesc()); 3663 } 3664 } 3665 currentPage = page; 3666 currentPageOriginalPerspective = page.getActivePerspective(); 3667 } 3668 page.bringToTop(part); 3669 // try to save the part 3670 int choice = SaveableHelper.savePart(saveable2, page.getWorkbenchWindow(), true); 3671 if (choice == ISaveablePart2.CANCEL) { 3672 // If the user cancels, don't restore the previous 3673 // workbench state, as that will 3674 // be an unexpected switch from the current state. 3675 return true; 3676 } else if (choice != ISaveablePart2.DEFAULT) { 3677 saveable2Processed = true; 3678 listIterator.remove(); 3679 } 3680 } 3681 } 3682 3683 // try to restore the workbench to its previous state 3684 if (currentPage != null && currentPageOriginalPerspective != null) { 3685 if (!currentPageOriginalPerspective.equals(currentPage.getActivePerspective())) { 3686 currentPage.setPerspective(currentPageOriginalPerspective.getDesc()); 3687 } 3688 } 3689 3690 // if processing a ISaveablePart2 caused other parts to be 3691 // saved, remove them from the list presented to the user. 3692 if (saveable2Processed) { 3693 removeNonDirtyParts(dirtyParts); 3694 } 3695 3696 return false; 3697 } 3698 removeNonDirtyParts(List<IWorkbenchPart> parts)3699 private static void removeNonDirtyParts(List<IWorkbenchPart> parts) { 3700 ListIterator<IWorkbenchPart> listIterator; 3701 listIterator = parts.listIterator(); 3702 while (listIterator.hasNext()) { 3703 ISaveablePart part = SaveableHelper.getSaveable(listIterator.next()); 3704 if (part == null || !part.isDirty()) { 3705 listIterator.remove(); 3706 } 3707 } 3708 } 3709 3710 /** 3711 * For each part (view or editor) in the given list, attempts to convert it to 3712 * one or more saveable models. Duplicate models are removed. If closing is 3713 * true, then models that will remain open in parts other than the given parts 3714 * are removed. 3715 * 3716 * @param parts the parts (list of IViewPart or IEditorPart) 3717 * @param closing whether the parts are being closed 3718 * @param addNonPartSources whether non-part sources should be added (true for 3719 * the Save All action, see bug 139004) 3720 * @return the dirty models 3721 */ convertToSaveables(List<IWorkbenchPart> parts, boolean closing, boolean addNonPartSources)3722 private static List<Saveable> convertToSaveables(List<IWorkbenchPart> parts, boolean closing, 3723 boolean addNonPartSources) { 3724 ArrayList<Saveable> result = new ArrayList<>(); 3725 HashSet<Saveable> seen = new HashSet<>(); 3726 for (IWorkbenchPart part : parts) { 3727 for (Saveable saveable : getSaveables(part)) { 3728 if (saveable.isDirty() && !seen.contains(saveable)) { 3729 seen.add(saveable); 3730 if (!closing || closingLastPartShowingModel(saveable, parts, part.getSite().getPage())) { 3731 result.add(saveable); 3732 } 3733 } 3734 } 3735 } 3736 if (addNonPartSources) { 3737 SaveablesList saveablesList = (SaveablesList) PlatformUI.getWorkbench() 3738 .getService(ISaveablesLifecycleListener.class); 3739 ISaveablesSource[] nonPartSources = saveablesList.getNonPartSources(); 3740 for (ISaveablesSource nonPartSource : nonPartSources) { 3741 for (Saveable saveable : nonPartSource.getSaveables()) { 3742 if (saveable.isDirty() && !seen.contains(saveable)) { 3743 seen.add(saveable); 3744 result.add(saveable); 3745 } 3746 } 3747 } 3748 } 3749 return result; 3750 } 3751 3752 /** 3753 * Returns the saveable models provided by the given part. If the part does not 3754 * provide any models, a default model is returned representing the part. 3755 * 3756 * @param part the workbench part 3757 * @return the saveable models 3758 */ getSaveables(IWorkbenchPart part)3759 private static Saveable[] getSaveables(IWorkbenchPart part) { 3760 if (part instanceof ISaveablesSource) { 3761 ISaveablesSource source = (ISaveablesSource) part; 3762 return source.getSaveables(); 3763 } 3764 return new Saveable[] { new DefaultSaveable(part) }; 3765 } 3766 3767 /** 3768 * Returns true if, in the given page, no more parts will reference the given 3769 * model if the given parts are closed. 3770 * 3771 * @param model the model 3772 * @param closingParts the parts being closed (list of IViewPart or IEditorPart) 3773 * @param page the page 3774 * @return <code>true</code> if no more parts in the page will reference the 3775 * given model, <code>false</code> otherwise 3776 */ closingLastPartShowingModel(Saveable model, List<IWorkbenchPart> closingParts, IWorkbenchPage page)3777 private static boolean closingLastPartShowingModel(Saveable model, List<IWorkbenchPart> closingParts, 3778 IWorkbenchPage page) { 3779 HashSet<IWorkbenchPart> closingPartsWithSameModel = new HashSet<>(); 3780 for (IWorkbenchPart part : closingParts) { 3781 Saveable[] models = getSaveables(part); 3782 if (Arrays.asList(models).contains(model)) { 3783 closingPartsWithSameModel.add(part); 3784 } 3785 } 3786 IWorkbenchPartReference[] pagePartRefs = ((WorkbenchPage) page).getSortedParts(); 3787 HashSet<IWorkbenchPart> pagePartsWithSameModels = new HashSet<>(); 3788 for (IWorkbenchPartReference partRef : pagePartRefs) { 3789 IWorkbenchPart part = partRef.getPart(false); 3790 if (part != null) { 3791 Saveable[] models = getSaveables(part); 3792 if (Arrays.asList(models).contains(model)) { 3793 pagePartsWithSameModels.add(part); 3794 } 3795 } 3796 } 3797 pagePartsWithSameModels.removeAll(closingPartsWithSameModel); 3798 return pagePartsWithSameModels.isEmpty(); 3799 } 3800 3801 /** 3802 * Saves the contents of the provided saveable and returns whether the operation 3803 * succeeded or not. 3804 * 3805 * @param saveable the saveable part to save 3806 * @param part 3807 * @param confirm whether the user should be prompted for confirmation of the 3808 * save request 3809 * @param closing whether the part will be closed after the save operation has 3810 * completed, this may determine whether whether the save 3811 * operation will actually be invoked or not 3812 * @return <code>true</code> if the saveable's contents has been persisted, 3813 * <code>false</code> otherwise 3814 * @see ISaveablePart#isSaveOnCloseNeeded() 3815 */ saveSaveable(ISaveablePart saveable, IWorkbenchPart part, boolean confirm, boolean closing)3816 public boolean saveSaveable(ISaveablePart saveable, IWorkbenchPart part, boolean confirm, boolean closing) { 3817 if (closing && !saveable.isSaveOnCloseNeeded()) { 3818 return true; 3819 } 3820 return SaveableHelper.savePart(saveable, part, legacyWindow, confirm); 3821 } 3822 3823 /** 3824 * Saves an editors in the workbench. If <code>confirm</code> is 3825 * <code>true</code> the user is prompted to confirm the command. 3826 * 3827 * @param confirm if user confirmation should be sought 3828 * @return <code>true</code> if the command succeeded, or <code>false</code> if 3829 * the user cancels the command 3830 */ 3831 @Override saveEditor(IEditorPart editor, boolean confirm)3832 public boolean saveEditor(IEditorPart editor, boolean confirm) { 3833 return saveSaveable(editor, editor, confirm, false); 3834 } 3835 3836 @Override savePerspective()3837 public void savePerspective() { 3838 throw new UnsupportedOperationException(); 3839 } 3840 3841 @Override savePerspectiveAs(IPerspectiveDescriptor perspective)3842 public void savePerspectiveAs(IPerspectiveDescriptor perspective) { 3843 MPerspective visiblePerspective = getPerspectiveStack().getSelectedElement(); 3844 // get the original perspective 3845 String originalPerspectiveId = visiblePerspective.getElementId(); 3846 IPerspectiveDescriptor originalPerspective = getWorkbenchWindow().getWorkbench().getPerspectiveRegistry() 3847 .findPerspectiveWithId(originalPerspectiveId); 3848 // remove it from our collection of previously opened perspectives 3849 sortedPerspectives.remove(originalPerspective); 3850 // append the saved perspective 3851 sortedPerspectives.add(perspective); 3852 3853 visiblePerspective.setLabel(perspective.getLabel()); 3854 visiblePerspective.setTooltip(perspective.getLabel()); 3855 visiblePerspective.setElementId(perspective.getId()); 3856 3857 MPerspective copy = (MPerspective) EcoreUtil.copy((EObject) visiblePerspective); 3858 3859 List<MPlaceholder> elementsToHide = modelService.findElements(copy, null, MPlaceholder.class, null); 3860 for (MPlaceholder elementToHide : elementsToHide) { 3861 if (elementToHide.isToBeRendered() 3862 && elementToHide.getRef().getTags().contains(IPresentationEngine.NO_RESTORE)) { 3863 elementToHide.setToBeRendered(false); 3864 updateSelectionAndParentVisibility(elementToHide); 3865 } 3866 } 3867 // remove placeholder refs and save as snippet 3868 modelService.cloneElement(copy, application); 3869 if (perspective instanceof PerspectiveDescriptor) { 3870 ((PerspectiveDescriptor) perspective).setHasCustomDefinition(true); 3871 } 3872 3873 UIEvents.publishEvent(UIEvents.UILifeCycle.PERSPECTIVE_SAVED, visiblePerspective); 3874 } 3875 updateSelectionAndParentVisibility(MUIElement element)3876 private void updateSelectionAndParentVisibility(MUIElement element) { 3877 MElementContainer<MUIElement> parent = element.getParent(); 3878 if (parent.getSelectedElement() == element) { 3879 parent.setSelectedElement(null); 3880 } 3881 int renderableChildren = modelService.countRenderableChildren(parent); 3882 if (renderableChildren == 0 && !modelService.isLastEditorStack(parent)) { 3883 parent.setToBeRendered(false); 3884 updateSelectionAndParentVisibility(parent); 3885 } 3886 } 3887 3888 @Override setEditorAreaVisible(boolean showEditorArea)3889 public void setEditorAreaVisible(boolean showEditorArea) { 3890 MUIElement find = findSharedArea(); 3891 if (find != null) { 3892 if (showEditorArea) { 3893 // make sure it's been rendered if it hasn't been 3894 find.setToBeRendered(true); 3895 } 3896 3897 // If the EA is minimized, restore it... 3898 if (showEditorArea) { 3899 find.getTags().remove(IPresentationEngine.MINIMIZED); 3900 } 3901 3902 find.setVisible(showEditorArea); 3903 } 3904 } 3905 3906 private HashMap<MPerspective, Perspective> modelToPerspectiveMapping = new HashMap<>(); 3907 getPerspective(MPerspective mperspective)3908 private Perspective getPerspective(MPerspective mperspective) { 3909 if (mperspective == null) { 3910 return null; 3911 } 3912 if (!modelToPerspectiveMapping.containsKey(mperspective)) { 3913 boolean fixedPerspective = false; 3914 PerspectiveDescriptor perspectiveDesc = (PerspectiveDescriptor) getPerspectiveDesc( 3915 mperspective.getElementId()); 3916 if (perspectiveDesc == null) { 3917 fixedPerspective = true; 3918 perspectiveDesc = fixOrphanPerspective(mperspective); 3919 } 3920 Perspective p = new Perspective(perspectiveDesc, mperspective, this); 3921 modelToPerspectiveMapping.put(mperspective, p); 3922 p.initActionSets(); 3923 if (fixedPerspective) { 3924 UIEvents.publishEvent(UIEvents.UILifeCycle.PERSPECTIVE_SAVED, mperspective); 3925 } 3926 } 3927 return modelToPerspectiveMapping.get(mperspective); 3928 } 3929 3930 /** 3931 * An 'orphan' perspective is one that was originally created through a 3932 * contribution but whose contributing bundle is no longer available. In order 3933 * to allow it to behave correctly within the environment (for Close, Reset...) 3934 * we turn it into a 'custom' perspective on its first activation. 3935 * 3936 * @return 3937 */ fixOrphanPerspective(MPerspective mperspective)3938 private PerspectiveDescriptor fixOrphanPerspective(MPerspective mperspective) { 3939 PerspectiveRegistry reg = (PerspectiveRegistry) PlatformUI.getWorkbench().getPerspectiveRegistry(); 3940 String perspId = mperspective.getElementId(); 3941 String label = mperspective.getLabel(); 3942 String msg = "Perspective with name '" + label + "' and id '" + perspId + "' has been made into a local copy"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ 3943 IStatus status = StatusUtil.newStatus(IStatus.WARNING, msg, null); 3944 StatusManager.getManager().handle(status, StatusManager.LOG); 3945 3946 String newDescId = NLS.bind(WorkbenchMessages.Perspective_localCopyLabel, label); 3947 while (reg.findPerspectiveWithId(newDescId) != null) { 3948 newDescId = NLS.bind(WorkbenchMessages.Perspective_localCopyLabel, newDescId); 3949 } 3950 PerspectiveDescriptor pd = new PerspectiveDescriptor(perspId, label, null); 3951 PerspectiveDescriptor newDesc = reg.createPerspective(newDescId, pd); 3952 if (mperspective.getIconURI() != null) { 3953 try { 3954 ImageDescriptor img = ImageDescriptor.createFromURL(new URI(mperspective.getIconURI()).toURL()); 3955 newDesc.setImageDescriptor(img); 3956 } catch (MalformedURLException | URISyntaxException e) { 3957 WorkbenchPlugin.log(MessageFormat.format("Error on applying configured perspective icon: {0}", //$NON-NLS-1$ 3958 mperspective.getIconURI(), e)); 3959 } 3960 } 3961 3962 mperspective.setElementId(newDesc.getId()); 3963 mperspective.setLabel(newDesc.getLabel()); 3964 sortedPerspectives.add(newDesc); 3965 modelService.cloneElement(mperspective, application); 3966 newDesc.setHasCustomDefinition(true); 3967 return newDesc; 3968 } 3969 3970 @Override setPerspective(IPerspectiveDescriptor perspective)3971 public void setPerspective(IPerspectiveDescriptor perspective) { 3972 BusyIndicator.showWhile(null, () -> busySetPerspective(perspective)); 3973 } 3974 busySetPerspective(IPerspectiveDescriptor perspective)3975 private void busySetPerspective(IPerspectiveDescriptor perspective) { 3976 if (perspective == null) { 3977 return; 3978 } 3979 3980 IPerspectiveDescriptor lastPerspective = getPerspective(); 3981 if (lastPerspective != null && lastPerspective.getId().equals(perspective.getId())) { 3982 // no change 3983 MPerspectiveStack perspectives = getPerspectiveStack(); 3984 for (MPerspective mperspective : perspectives.getChildren()) { 3985 if (mperspective.getElementId().equals(perspective.getId())) { 3986 handleNullRefPlaceHolders(mperspective, window); 3987 } 3988 } 3989 return; 3990 } 3991 3992 MPerspectiveStack perspectives = getPerspectiveStack(); 3993 for (MPerspective mperspective : perspectives.getChildren()) { 3994 if (mperspective.getElementId().equals(perspective.getId())) { 3995 if (lastPerspective != null) { 3996 legacyWindow.firePerspectiveDeactivated(this, lastPerspective); 3997 } 3998 3999 // this perspective already exists, switch to this one 4000 perspectives.setSelectedElement(mperspective); 4001 mperspective.getContext().activate(); 4002 handleNullRefPlaceHolders(mperspective, window); 4003 return; 4004 } 4005 } 4006 4007 MPerspective modelPerspective = (MPerspective) modelService.cloneSnippet(application, perspective.getId(), 4008 window); 4009 4010 if (modelPerspective == null) { 4011 // couldn't find the perspective, create a new one 4012 modelPerspective = createPerspective(perspective); 4013 } 4014 4015 handleNullRefPlaceHolders(modelPerspective, window); 4016 4017 modelPerspective.setLabel(perspective.getLabel()); 4018 4019 ImageDescriptor imageDescriptor = perspective.getImageDescriptor(); 4020 if (imageDescriptor != null) { 4021 String imageURL = MenuHelper.getImageUrl(imageDescriptor); 4022 modelPerspective.setIconURI(imageURL); 4023 } 4024 4025 if (lastPerspective != null) { 4026 legacyWindow.firePerspectiveDeactivated(this, lastPerspective); 4027 } 4028 4029 // Hide placeholders for parts that exist in the 'global' areas 4030 modelService.hideLocalPlaceholders(window, modelPerspective); 4031 4032 // add it to the stack 4033 perspectives.getChildren().add(modelPerspective); 4034 // activate it 4035 perspectives.setSelectedElement(modelPerspective); 4036 4037 modelPerspective.getContext().activate(); 4038 modelPerspective.getContext().set(ISelectionService.class, selectionService); 4039 4040 legacyWindow.firePerspectiveOpened(this, perspective); 4041 UIEvents.publishEvent(UIEvents.UILifeCycle.PERSPECTIVE_OPENED, modelPerspective); 4042 } 4043 handleNullRefPlaceHolders(MUIElement element, MWindow refWin)4044 private void handleNullRefPlaceHolders(MUIElement element, MWindow refWin) { 4045 List<MPlaceholder> nullRefList = ((ModelServiceImpl) modelService).getNullRefPlaceHolders(element, refWin); 4046 4047 List<MPart> partList = modelService.findElements(element, null, MPart.class); 4048 for (MPart part : partList) { 4049 if (CompatibilityPart.COMPATIBILITY_VIEW_URI.equals(part.getContributionURI()) 4050 && part.getIconURI() == null) { 4051 part.getTransientData().put(IPresentationEngine.OVERRIDE_ICON_IMAGE_KEY, 4052 ImageDescriptor.getMissingImageDescriptor().createImage()); 4053 } 4054 } 4055 4056 if (nullRefList != null && nullRefList.size() > 0) { 4057 for (MPlaceholder ph : nullRefList) { 4058 if (ph.isToBeRendered()) { 4059 replacePlaceholder(ph); 4060 } 4061 } 4062 } 4063 } 4064 replacePlaceholder(MPlaceholder ph)4065 private void replacePlaceholder(MPlaceholder ph) { 4066 MPart part = modelService.createModelElement(MPart.class); 4067 part.setElementId(ph.getElementId()); 4068 part.getTransientData().put(IPresentationEngine.OVERRIDE_ICON_IMAGE_KEY, 4069 ImageDescriptor.getMissingImageDescriptor().createImage()); 4070 String label = (String) ph.getTransientData().get(IWorkbenchConstants.TAG_LABEL); 4071 if (label != null) { 4072 part.setLabel(label); 4073 } else { 4074 part.setLabel(getLabel(ph.getElementId())); 4075 } 4076 part.setContributionURI(CompatibilityPart.COMPATIBILITY_VIEW_URI); 4077 part.setCloseable(true); 4078 MElementContainer<MUIElement> curParent = ph.getParent(); 4079 int curIndex = curParent.getChildren().indexOf(ph); 4080 curParent.getChildren().remove(curIndex); 4081 curParent.getChildren().add(curIndex, part); 4082 if (curParent.getSelectedElement() == ph) { 4083 curParent.setSelectedElement(part); 4084 } 4085 } 4086 getLabel(String str)4087 private String getLabel(String str) { 4088 int index = str.lastIndexOf('.'); 4089 if (index == -1) 4090 return str; 4091 return str.substring(index + 1); 4092 } 4093 4094 /** 4095 * @param perspective 4096 * @return never null 4097 */ createPerspective(IPerspectiveDescriptor perspective)4098 private MPerspective createPerspective(IPerspectiveDescriptor perspective) { 4099 MPerspective modelPerspective = modelService.createModelElement(MPerspective.class); 4100 4101 // tag it with the same id 4102 modelPerspective.setElementId(perspective.getId()); 4103 4104 // instantiate the perspective 4105 IPerspectiveFactory factory = ((PerspectiveDescriptor) perspective).createFactory(); 4106 ModeledPageLayout modelLayout = new ModeledPageLayout(window, modelService, partService, modelPerspective, 4107 perspective, this, true); 4108 factory.createInitialLayout(modelLayout); 4109 PerspectiveTagger.tagPerspective(modelPerspective, modelService); 4110 PerspectiveExtensionReader reader = new PerspectiveExtensionReader(); 4111 reader.extendLayout(getExtensionTracker(), perspective.getId(), modelLayout); 4112 return modelPerspective; 4113 } 4114 perspectiveActionSetChanged(Perspective perspective, IActionSetDescriptor descriptor, int changeType)4115 void perspectiveActionSetChanged(Perspective perspective, IActionSetDescriptor descriptor, int changeType) { 4116 if (perspective == getActivePerspective()) { 4117 actionSets.change(descriptor, changeType); 4118 } 4119 } 4120 4121 /** 4122 * Retrieves the perspective stack of the window that's containing this 4123 * workbench page. 4124 * 4125 * @return the stack of perspectives of this page's containing window 4126 */ getPerspectiveStack()4127 private MPerspectiveStack getPerspectiveStack() { 4128 if (_perspectiveStack != null) { 4129 return _perspectiveStack; 4130 } 4131 List<MPerspectiveStack> theStack = modelService.findElements(window, null, MPerspectiveStack.class); 4132 if (theStack.size() > 0) { 4133 _perspectiveStack = theStack.get(0); 4134 return _perspectiveStack; 4135 } 4136 4137 for (MWindowElement child : window.getChildren()) { 4138 if (child instanceof MPerspectiveStack) { 4139 _perspectiveStack = (MPerspectiveStack) child; 4140 return _perspectiveStack; 4141 } 4142 } 4143 4144 MPartSashContainer stickySash = modelService.createModelElement(MPartSashContainer.class); 4145 stickySash.setHorizontal(true); 4146 4147 MPerspectiveStack perspectiveStack = modelService.createModelElement(MPerspectiveStack.class); 4148 perspectiveStack.setElementId(IWorkbenchConstants.PERSPECTIVE_STACK_ID); 4149 perspectiveStack.setContainerData("7500"); //$NON-NLS-1$ 4150 4151 MPartStack stickyFolder = modelService.createModelElement(MPartStack.class); 4152 stickyFolder.setContainerData("2500"); //$NON-NLS-1$ 4153 stickyFolder.setElementId("stickyFolderRight"); //$NON-NLS-1$ 4154 stickyFolder.setToBeRendered(false); 4155 4156 IStickyViewDescriptor[] stickyViews = getWorkbenchWindow().getWorkbench().getViewRegistry().getStickyViews(); 4157 for (IStickyViewDescriptor stickyView : stickyViews) { 4158 if (stickyView.getLocation() == IPageLayout.RIGHT) { 4159 MStackElement viewModel = ModeledPageLayout.createViewModel(application, stickyView.getId(), false, 4160 this, partService, true); 4161 stickyFolder.getChildren().add(viewModel); 4162 } 4163 } 4164 4165 stickySash.getChildren().add(perspectiveStack); 4166 stickySash.getChildren().add(stickyFolder); 4167 stickySash.setSelectedElement(perspectiveStack); 4168 4169 window.getChildren().add(stickySash); 4170 window.setSelectedElement(stickySash); 4171 _perspectiveStack = perspectiveStack; 4172 return perspectiveStack; 4173 } 4174 4175 /** 4176 * Sets the active working set for the workbench page. Notifies property change 4177 * listener about the change. 4178 * 4179 * @param newWorkingSet the active working set for the page. May be null. 4180 * @since 2.0 4181 * @deprecated individual views should store a working set if needed 4182 */ 4183 @Deprecated setWorkingSet(IWorkingSet newWorkingSet)4184 public void setWorkingSet(IWorkingSet newWorkingSet) { 4185 IWorkingSet oldWorkingSet = workingSet; 4186 4187 workingSet = newWorkingSet; 4188 if (oldWorkingSet != newWorkingSet) { 4189 firePropertyChange(CHANGE_WORKING_SET_REPLACE, oldWorkingSet, newWorkingSet); 4190 } 4191 if (newWorkingSet != null) { 4192 WorkbenchPlugin.getDefault().getWorkingSetManager() 4193 .addPropertyChangeListener(workingSetPropertyChangeListener); 4194 } else { 4195 WorkbenchPlugin.getDefault().getWorkingSetManager() 4196 .removePropertyChangeListener(workingSetPropertyChangeListener); 4197 } 4198 } 4199 4200 /** 4201 * @see IWorkbenchPage 4202 */ 4203 @Override showActionSet(String actionSetID)4204 public void showActionSet(String actionSetID) { 4205 Perspective persp = getActivePerspective(); 4206 if (persp != null) { 4207 ActionSetRegistry reg = WorkbenchPlugin.getDefault().getActionSetRegistry(); 4208 4209 IActionSetDescriptor desc = reg.findActionSet(actionSetID); 4210 if (desc != null) { 4211 List<IActionSetDescriptor> offActionSets = persp.getAlwaysOffActionSets(); 4212 for (IActionSetDescriptor off : offActionSets) { 4213 if (off.getId().equals(desc.getId())) { 4214 return; 4215 } 4216 } 4217 persp.addActionSet(desc); 4218 legacyWindow.updateActionSets(); 4219 legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_ACTION_SET_SHOW); 4220 } 4221 } 4222 } 4223 4224 /** 4225 * See IWorkbenchPage. 4226 */ 4227 @Override showView(String viewID)4228 public IViewPart showView(String viewID) throws PartInitException { 4229 return showView(viewID, null, VIEW_ACTIVATE); 4230 } 4231 4232 @Override showView(final String viewID, final String secondaryID, final int mode)4233 public IViewPart showView(final String viewID, final String secondaryID, final int mode) throws PartInitException { 4234 4235 if (secondaryID != null) { 4236 if (secondaryID.length() == 0 || secondaryID.indexOf(':') != -1) { 4237 throw new IllegalArgumentException(WorkbenchMessages.WorkbenchPage_IllegalSecondaryId); 4238 } 4239 } 4240 if (!certifyMode(mode)) { 4241 throw new IllegalArgumentException(WorkbenchMessages.WorkbenchPage_IllegalViewMode); 4242 } 4243 4244 // Run op in busy cursor. 4245 final String compoundId = secondaryID != null ? viewID + ':' + secondaryID : viewID; 4246 final Object[] result = new Object[1]; 4247 BusyIndicator.showWhile(null, () -> { 4248 try { 4249 result[0] = busyShowView(compoundId, mode); 4250 } catch (PartInitException e) { 4251 result[0] = e; 4252 } 4253 }); 4254 if (result[0] instanceof IViewPart) { 4255 return (IViewPart) result[0]; 4256 } else if (result[0] instanceof PartInitException) { 4257 throw (PartInitException) result[0]; 4258 } else { 4259 throw new PartInitException(WorkbenchMessages.WorkbenchPage_AbnormalWorkbenchCondition); 4260 } 4261 } 4262 4263 /** 4264 * @param mode the mode to test 4265 * @return whether the mode is recognized 4266 * @since 3.0 4267 */ certifyMode(int mode)4268 private boolean certifyMode(int mode) { 4269 switch (mode) { 4270 case VIEW_ACTIVATE: 4271 case VIEW_VISIBLE: 4272 case VIEW_CREATE: 4273 return true; 4274 default: 4275 return false; 4276 } 4277 } 4278 getActiveElement(IWorkbenchPartReference ref)4279 public MUIElement getActiveElement(IWorkbenchPartReference ref) { 4280 MUIElement element = null; 4281 4282 MPerspective curPersp = modelService.getActivePerspective(window); 4283 if (curPersp == null) 4284 return null; 4285 4286 MPlaceholder eaPH = (MPlaceholder) modelService.find(IPageLayout.ID_EDITOR_AREA, curPersp); 4287 MPart model = ((WorkbenchPartReference) ref).getModel(); 4288 MPlaceholder placeholder = model.getCurSharedRef(); 4289 4290 switch (modelService.getElementLocation(placeholder == null ? model : placeholder)) { 4291 case EModelService.IN_ACTIVE_PERSPECTIVE: 4292 case EModelService.OUTSIDE_PERSPECTIVE: 4293 MUIElement parent = placeholder == null ? model.getParent() : placeholder.getParent(); 4294 if (parent instanceof MPartStack) { 4295 element = parent; 4296 } 4297 break; 4298 case EModelService.IN_SHARED_AREA: 4299 element = eaPH; 4300 break; 4301 } 4302 return element; 4303 } 4304 4305 @Override setPartState(IWorkbenchPartReference ref, int iState)4306 public void setPartState(IWorkbenchPartReference ref, int iState) { 4307 MUIElement element = getActiveElement(ref); 4308 String state = null; 4309 4310 if (iState == STATE_MINIMIZED) { 4311 state = IPresentationEngine.MINIMIZED; 4312 } else if (iState == STATE_MAXIMIZED) { 4313 state = IPresentationEngine.MAXIMIZED; 4314 } 4315 setPartState(element, state); 4316 } 4317 4318 @Override getPartState(IWorkbenchPartReference ref)4319 public int getPartState(IWorkbenchPartReference ref) { 4320 int state = STATE_RESTORED; 4321 MUIElement element = getActiveElement(ref); 4322 4323 if (element != null) { 4324 if (element.getTags().contains(IPresentationEngine.MINIMIZED)) { 4325 state = STATE_MINIMIZED; 4326 } else if (element.getTags().contains(IPresentationEngine.MAXIMIZED)) { 4327 state = STATE_MAXIMIZED; 4328 } 4329 } 4330 return state; 4331 } 4332 4333 // if the state is null, then we'll just restore the view setPartState(MUIElement element, String state)4334 private void setPartState(MUIElement element, String state) { 4335 if (element != null) { 4336 element.getTags().remove(IPresentationEngine.MINIMIZED_BY_ZOOM); 4337 if (IPresentationEngine.MINIMIZED.equals(state)) { 4338 element.getTags().remove(IPresentationEngine.MAXIMIZED); 4339 element.getTags().add(IPresentationEngine.MINIMIZED); 4340 } else if (IPresentationEngine.MAXIMIZED.equals(state)) { 4341 element.getTags().remove(IPresentationEngine.MINIMIZED); 4342 element.getTags().add(IPresentationEngine.MAXIMIZED); 4343 } else { 4344 element.getTags().remove(IPresentationEngine.MINIMIZED); 4345 element.getTags().remove(IPresentationEngine.MAXIMIZED); 4346 } 4347 } 4348 } 4349 4350 /** 4351 * updateActionBars method comment. 4352 */ updateActionBars()4353 public void updateActionBars() { 4354 legacyWindow.updateActionBars(); 4355 } 4356 4357 @Override zoomOut()4358 public void zoomOut() { 4359 // TODO compat: what does the zoom do? 4360 } 4361 4362 @Override toggleZoom(IWorkbenchPartReference ref)4363 public void toggleZoom(IWorkbenchPartReference ref) { 4364 MUIElement element = getActiveElement(ref); 4365 if (element != null) { 4366 String state = null; 4367 if (!element.getTags().contains(IPresentationEngine.MAXIMIZED)) { 4368 state = IPresentationEngine.MAXIMIZED; 4369 } 4370 this.setPartState(element, state); 4371 } 4372 } 4373 4374 @Override getOpenPerspectives()4375 public IPerspectiveDescriptor[] getOpenPerspectives() { 4376 MPerspectiveStack perspectiveStack = modelService.findElements(window, null, MPerspectiveStack.class).get(0); 4377 IPerspectiveRegistry registry = PlatformUI.getWorkbench().getPerspectiveRegistry(); 4378 4379 ArrayList<IPerspectiveDescriptor> tmp = new ArrayList<>(perspectiveStack.getChildren().size()); 4380 for (MPerspective persp : perspectiveStack.getChildren()) { 4381 String perspectiveId = persp.getElementId(); 4382 IPerspectiveDescriptor desc = registry.findPerspectiveWithId(perspectiveId); 4383 if (desc != null) { 4384 tmp.add(desc); 4385 } 4386 } 4387 IPerspectiveDescriptor[] descs = new IPerspectiveDescriptor[tmp.size()]; 4388 tmp.toArray(descs); 4389 4390 return descs; 4391 } 4392 4393 @Override getSortedPerspectives()4394 public IPerspectiveDescriptor[] getSortedPerspectives() { 4395 return sortedPerspectives.toArray(new IPerspectiveDescriptor[sortedPerspectives.size()]); 4396 } 4397 4398 /** 4399 * Returns the reference to the given part, or <code>null</code> if it has no 4400 * reference (i.e. it is not a top-level part in this workbench page). 4401 * 4402 * @param part the part 4403 * @return the part's reference or <code>null</code> if the given part does not 4404 * belong to this workbench page 4405 */ 4406 @Override getReference(IWorkbenchPart part)4407 public IWorkbenchPartReference getReference(IWorkbenchPart part) { 4408 if (part != null) { 4409 IWorkbenchPartSite site = part.getSite(); 4410 if (site instanceof PartSite) { 4411 return ((PartSite) site).getPartReference(); 4412 } 4413 } 4414 return null; 4415 } 4416 getCurrentPerspective()4417 public MPerspective getCurrentPerspective() { 4418 MPerspectiveStack stack = getPerspectiveStack(); 4419 return stack == null ? null : stack.getSelectedElement(); 4420 } 4421 getActivePerspective()4422 Perspective getActivePerspective() { 4423 return getPerspective(getCurrentPerspective()); 4424 } 4425 4426 @Override getViewStack(IViewPart part)4427 public IViewPart[] getViewStack(IViewPart part) { 4428 String compoundId = PagePartSelectionTracker.getPartId(part); 4429 MPart mpart = partService.findPart(compoundId); 4430 if (mpart != null) { 4431 MElementContainer<?> parent = mpart.getParent(); 4432 if (parent == null) { 4433 // this is a shared part, check for placeholders 4434 MPlaceholder placeholder = mpart.getCurSharedRef(); 4435 if (placeholder != null) { 4436 parent = placeholder.getParent(); 4437 } 4438 } 4439 4440 if (parent instanceof MPartStack) { 4441 MStackElement selectedElement = ((MPartStack) parent).getSelectedElement(); 4442 final MUIElement topPart = selectedElement instanceof MPlaceholder 4443 ? ((MPlaceholder) selectedElement).getRef() 4444 : null; 4445 4446 List<CompatibilityView> stack = new ArrayList<>(); 4447 for (Object child : parent.getChildren()) { 4448 MPart siblingPart = child instanceof MPart ? (MPart) child 4449 : (MPart) ((MPlaceholder) child).getRef(); 4450 // Bug 398433 - guard against NPE 4451 Object siblingObject = siblingPart != null ? siblingPart.getObject() : null; 4452 if (siblingObject instanceof CompatibilityView) { 4453 stack.add((CompatibilityView) siblingObject); 4454 } 4455 } 4456 4457 // sort the list by activation order (most recently activated 4458 // first) 4459 stack.sort((o1, o2) -> { 4460 MPart model1 = o1.getModel(); 4461 MPart model2 = o2.getModel(); 4462 4463 /* 4464 * WORKAROUND: Since we only have the activation list and not a bingToTop list, 4465 * we can't set/know the order for inactive stacks. This workaround makes sure 4466 * that the topmost part is at least at the first position. 4467 */ 4468 if (model1 == topPart) 4469 return Integer.MIN_VALUE; 4470 if (model2 == topPart) 4471 return Integer.MAX_VALUE; 4472 4473 int pos1 = activationList.indexOf(model1); 4474 int pos2 = activationList.indexOf(model2); 4475 if (pos1 == -1) 4476 pos1 = Integer.MAX_VALUE; 4477 if (pos2 == -1) 4478 pos2 = Integer.MAX_VALUE; 4479 return pos1 - pos2; 4480 }); 4481 4482 IViewPart[] result = new IViewPart[stack.size()]; 4483 for (int i = 0; i < result.length; i++) { 4484 result[i] = stack.get(i).getView(); 4485 } 4486 return result; 4487 } 4488 4489 // not in a stack, standalone 4490 return new IViewPart[] { part }; 4491 } 4492 return null; 4493 } 4494 4495 @Override getExtensionTracker()4496 public IExtensionTracker getExtensionTracker() { 4497 if (tracker == null) { 4498 tracker = new UIExtensionTracker(getWorkbenchWindow().getWorkbench().getDisplay()); 4499 } 4500 return tracker; 4501 } 4502 4503 private static final String[] EMPTY_STRING_ARRAY = new String[0]; 4504 getArrayForTag(String tagPrefix)4505 private String[] getArrayForTag(String tagPrefix) { 4506 List<String> id = getCollectionForTag(tagPrefix); 4507 if (id == null) 4508 return EMPTY_STRING_ARRAY; 4509 return id.toArray(new String[id.size()]); 4510 } 4511 getCollectionForTag(String tagPrefix)4512 private List<String> getCollectionForTag(String tagPrefix) { 4513 MPerspective perspective = getPerspectiveStack().getSelectedElement(); 4514 if (perspective == null) { 4515 return Collections.emptyList(); 4516 } 4517 return ModeledPageLayout.getIds(perspective, tagPrefix); 4518 } 4519 4520 @Override getNewWizardShortcuts()4521 public String[] getNewWizardShortcuts() { 4522 return getArrayForTag(ModeledPageLayout.NEW_WIZARD_TAG); 4523 } 4524 4525 @Override getPerspectiveShortcuts()4526 public String[] getPerspectiveShortcuts() { 4527 return getArrayForTag(ModeledPageLayout.PERSP_SHORTCUT_TAG); 4528 } 4529 4530 @Override getShowViewShortcuts()4531 public String[] getShowViewShortcuts() { 4532 return getArrayForTag(ModeledPageLayout.SHOW_VIEW_TAG); 4533 } 4534 isPartVisible(IWorkbenchPartReference reference)4535 public boolean isPartVisible(IWorkbenchPartReference reference) { 4536 IWorkbenchPart part = reference.getPart(false); 4537 // Can't be visible if it isn't created yet 4538 if (part == null) { 4539 return false; 4540 } 4541 4542 return isPartVisible(part); 4543 } 4544 4545 @Override getWorkingSets()4546 public IWorkingSet[] getWorkingSets() { 4547 return workingSets; 4548 } 4549 4550 @Override setWorkingSets(IWorkingSet[] newWorkingSets)4551 public void setWorkingSets(IWorkingSet[] newWorkingSets) { 4552 if (newWorkingSets != null) { 4553 WorkbenchPlugin.getDefault().getWorkingSetManager() 4554 .addPropertyChangeListener(workingSetPropertyChangeListener); 4555 } else { 4556 WorkbenchPlugin.getDefault().getWorkingSetManager() 4557 .removePropertyChangeListener(workingSetPropertyChangeListener); 4558 } 4559 4560 if (newWorkingSets == null) { 4561 newWorkingSets = new IWorkingSet[0]; 4562 } 4563 4564 IWorkingSet[] oldWorkingSets = workingSets; 4565 4566 // filter out any duplicates if necessary 4567 if (newWorkingSets.length > 1) { 4568 Set<IWorkingSet> setOfSets = new HashSet<>(); 4569 for (IWorkingSet workingSet : newWorkingSets) { 4570 if (workingSet == null) { 4571 throw new IllegalArgumentException(); 4572 } 4573 setOfSets.add(workingSet); 4574 } 4575 newWorkingSets = setOfSets.toArray(new IWorkingSet[setOfSets.size()]); 4576 } 4577 4578 workingSets = newWorkingSets; 4579 if (!Arrays.equals(oldWorkingSets, newWorkingSets)) { 4580 firePropertyChange(CHANGE_WORKING_SETS_REPLACE, oldWorkingSets, newWorkingSets); 4581 if (aggregateWorkingSet != null) { 4582 aggregateWorkingSet.setComponents(workingSets); 4583 } 4584 } 4585 } 4586 4587 @Override getAggregateWorkingSet()4588 public IWorkingSet getAggregateWorkingSet() { 4589 if (aggregateWorkingSet == null) { 4590 IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager(); 4591 4592 if (aggregateWorkingSetId == null) { 4593 aggregateWorkingSetId = generateAggregateWorkingSetId(); 4594 } else { 4595 aggregateWorkingSet = (AggregateWorkingSet) workingSetManager.getWorkingSet(aggregateWorkingSetId); 4596 } 4597 if (aggregateWorkingSet == null) { 4598 aggregateWorkingSet = (AggregateWorkingSet) workingSetManager.createAggregateWorkingSet( 4599 aggregateWorkingSetId, WorkbenchMessages.WorkbenchPage_workingSet_default_label, 4600 getWorkingSets()); 4601 workingSetManager.addWorkingSet(aggregateWorkingSet); 4602 } 4603 } 4604 return aggregateWorkingSet; 4605 } 4606 generateAggregateWorkingSetId()4607 private String generateAggregateWorkingSetId() { 4608 return "Aggregate for window " + System.currentTimeMillis(); //$NON-NLS-1$ 4609 } 4610 4611 @Override showEditor(IEditorReference ref)4612 public void showEditor(IEditorReference ref) { 4613 IWorkbenchPart wPart = ref.getPart(false); 4614 MPart part = ((EditorReference) ref).getModel(); 4615 part.setVisible(true); 4616 4617 // Workaround to get content visible. Otherwise the content sometimes is not 4618 // rendered. 4619 MElementContainer<MUIElement> partStack = part.getParent(); 4620 partStack.setSelectedElement(null); 4621 partStack.setSelectedElement(part); 4622 wPart.setFocus(); 4623 } 4624 4625 @Override hideEditor(IEditorReference ref)4626 public void hideEditor(IEditorReference ref) { 4627 MPart part = ((EditorReference) ref).getModel(); 4628 part.setVisible(false); 4629 } 4630 getEditorImageURI(EditorReference reference)4631 private String getEditorImageURI(EditorReference reference) { 4632 String iconURI = null; 4633 4634 EditorDescriptor descriptor = reference.getDescriptor(); 4635 if (descriptor != null) { 4636 IConfigurationElement element = descriptor.getConfigurationElement(); 4637 if (element != null) { 4638 iconURI = MenuHelper.getIconURI(element, IWorkbenchRegistryConstants.ATT_ICON); 4639 } 4640 } 4641 return iconURI; 4642 } 4643 4644 @Override getEditorState(IEditorReference[] editorRefs, boolean includeInputState)4645 public IMemento[] getEditorState(IEditorReference[] editorRefs, boolean includeInputState) { 4646 IMemento[] m = new IMemento[editorRefs.length]; 4647 for (int i = 0; i < editorRefs.length; i++) { 4648 m[i] = ((EditorReference) editorRefs[i]).getEditorState(); 4649 if (!includeInputState && m[i] != null) { 4650 m[i] = m[i].getChild(IWorkbenchConstants.TAG_EDITOR_STATE); 4651 } 4652 } 4653 return m; 4654 } 4655 4656 @Override openEditors(IEditorInput[] inputs, String[] editorIDs, int matchFlags)4657 public IEditorReference[] openEditors(IEditorInput[] inputs, String[] editorIDs, int matchFlags) 4658 throws MultiPartInitException { 4659 return openEditors(inputs, editorIDs, null, matchFlags, 0); 4660 } 4661 4662 @Override openEditors(IEditorInput[] inputs, String[] editorIDs, IMemento[] mementos, int matchFlags, int activationIndex)4663 public IEditorReference[] openEditors(IEditorInput[] inputs, String[] editorIDs, IMemento[] mementos, 4664 int matchFlags, int activationIndex) throws MultiPartInitException { 4665 // If we are only working with mementos create a placeholder array of 4666 // nulls 4667 if (inputs == null) { 4668 Assert.isTrue(mementos != null); 4669 inputs = new IEditorInput[mementos.length]; 4670 } 4671 4672 // If we are only working with mementos create a placeholder array of 4673 // nulls 4674 if (editorIDs == null) { 4675 Assert.isTrue(mementos != null); 4676 editorIDs = new String[mementos.length]; 4677 } 4678 4679 Assert.isTrue(inputs.length == editorIDs.length); 4680 Assert.isTrue(inputs.length > 0); 4681 Assert.isTrue(mementos == null || mementos.length == inputs.length); 4682 4683 PartInitException[] exceptions = new PartInitException[inputs.length]; 4684 IEditorReference[] references = new IEditorReference[inputs.length]; 4685 boolean hasFailures = false; 4686 4687 IEditorRegistry reg = getWorkbenchWindow().getWorkbench().getEditorRegistry(); 4688 MPart editorToActivate = null; 4689 for (int i = 0; i < inputs.length; i++) { 4690 String curEditorID = editorIDs[i]; 4691 IEditorInput curInput = inputs[i]; 4692 IMemento curMemento = mementos == null ? null : mementos[i]; 4693 4694 // If we don't have an editorID get it from the memento 4695 if (curEditorID == null && curMemento != null) { 4696 curEditorID = curMemento.getString(IWorkbenchConstants.TAG_ID); 4697 } 4698 4699 // If we don't have an input create on from the memento 4700 if (curInput == null && curMemento != null) { 4701 try { 4702 curInput = EditorReference.createInput(curMemento); 4703 } catch (PartInitException e) { 4704 curInput = null; 4705 exceptions[i] = e; 4706 hasFailures = true; 4707 continue; 4708 } 4709 } 4710 4711 // Adjust the memento so that it's always 'comlpete (i.e. including 4712 // both input and editor state) 4713 if (curMemento != null && !curMemento.getID().equals(IWorkbenchConstants.TAG_EDITOR)) { 4714 XMLMemento outerMem = XMLMemento.createWriteRoot(IWorkbenchConstants.TAG_EDITOR); 4715 outerMem.putString(IWorkbenchConstants.TAG_ID, curEditorID); 4716 outerMem.copyChild(curMemento); 4717 4718 XMLMemento inputMem = (XMLMemento) outerMem.createChild(IWorkbenchConstants.TAG_INPUT); 4719 inputMem.putString(IWorkbenchConstants.TAG_FACTORY_ID, curInput.getPersistable().getFactoryId()); 4720 inputMem.putString(IWorkbenchConstants.TAG_PATH, curInput.getName()); 4721 } 4722 4723 // OK, by this point we should have the EditorInput, the editor ID 4724 // and the memento (if any) 4725 if (reg.findEditor(curEditorID) == null) { 4726 references[i] = null; 4727 exceptions[i] = new PartInitException( 4728 NLS.bind(WorkbenchMessages.EditorManager_unknownEditorIDMessage, curEditorID)); 4729 hasFailures = true; 4730 } else if (curInput == null) { 4731 references[i] = null; 4732 exceptions[i] = new PartInitException( 4733 NLS.bind(WorkbenchMessages.EditorManager_no_persisted_state, curEditorID)); 4734 hasFailures = true; 4735 } else { 4736 // Is there an existing editor ? 4737 IEditorReference[] existingEditors = findEditors(curInput, curEditorID, matchFlags); 4738 if (existingEditors.length == 0) { 4739 MPart editor = partService.createPart(CompatibilityEditor.MODEL_ELEMENT_ID); 4740 references[i] = createEditorReferenceForPart(editor, curInput, curEditorID, null); 4741 4742 if (i == activationIndex) 4743 editorToActivate = editor; 4744 4745 // Set the information in the supplied IMemento into the 4746 // editor's model 4747 if (curMemento instanceof XMLMemento) { 4748 XMLMemento memento = (XMLMemento) curMemento; 4749 StringWriter writer = new StringWriter(); 4750 try { 4751 memento.save(writer); 4752 editor.getPersistedState().put(WorkbenchPartReference.MEMENTO_KEY, writer.toString()); 4753 } catch (IOException e) { 4754 WorkbenchPlugin.log(e); 4755 } 4756 } 4757 4758 editor.setLabel(references[i].getTitle()); 4759 editor.setTooltip(references[i].getTitleToolTip()); 4760 editor.setIconURI(getEditorImageURI((EditorReference) references[i])); 4761 ((PartServiceImpl) partService).addPart(editor); 4762 } else { 4763 // Use the existing editor, update the state if it has *not* 4764 // been rendered 4765 EditorReference ee = (EditorReference) existingEditors[0]; 4766 if (i == activationIndex) 4767 editorToActivate = ee.getModel(); 4768 4769 if (ee.getModel().getWidget() == null) { 4770 // Set the information in the supplied IMemento into the 4771 // editor's model 4772 if (curMemento instanceof XMLMemento) { 4773 XMLMemento momento = (XMLMemento) curMemento; 4774 StringWriter writer = new StringWriter(); 4775 try { 4776 momento.save(writer); 4777 ee.getModel().getPersistedState().put(WorkbenchPartReference.MEMENTO_KEY, 4778 writer.toString()); 4779 } catch (IOException e) { 4780 WorkbenchPlugin.log(e); 4781 } 4782 } 4783 } else { 4784 // editor already rendered, try to update its state 4785 if (curMemento != null && ee.getModel().getObject() instanceof CompatibilityEditor) { 4786 CompatibilityEditor ce = (CompatibilityEditor) ee.getModel().getObject(); 4787 if (ce.getEditor() instanceof IPersistableEditor) { 4788 IPersistableEditor pe = (IPersistableEditor) ce.getEditor(); 4789 4790 // Extract the 'editorState' from the memento 4791 IMemento editorMem = curMemento.getChild(IWorkbenchConstants.TAG_EDITOR_STATE); 4792 if (editorMem == null) { 4793 // Must be an externally defined memento, 4794 // take the second child 4795 IMemento[] kids = curMemento.getChildren(); 4796 if (kids.length == 2) 4797 editorMem = kids[1]; 4798 } 4799 if (editorMem != null) 4800 pe.restoreState(editorMem); 4801 } 4802 } 4803 } 4804 } 4805 } 4806 } 4807 4808 if (editorToActivate != null) { 4809 partService.activate(editorToActivate); 4810 } 4811 4812 boolean hasSuccesses = false; 4813 for (IEditorReference reference : references) { 4814 if (reference != null) { 4815 hasSuccesses = true; 4816 legacyWindow.firePerspectiveChanged(this, getPerspective(), reference, CHANGE_EDITOR_OPEN); 4817 } 4818 } 4819 4820 // only fire this event if an editor was opened 4821 if (hasSuccesses) { 4822 legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_EDITOR_OPEN); 4823 } 4824 4825 if (hasFailures) { 4826 throw new MultiPartInitException(references, exceptions); 4827 } 4828 4829 return references; 4830 } 4831 updatePerspectiveActionSets()4832 void updatePerspectiveActionSets() { 4833 updateActionSets(null, getActivePerspective()); 4834 } 4835 fireInitialPartVisibilityEvents()4836 void fireInitialPartVisibilityEvents() { 4837 MPerspective selectedElement = getPerspectiveStack().getSelectedElement(); 4838 // technically shouldn't be null here 4839 if (selectedElement != null) { 4840 Collection<MPart> parts = modelService.findElements(selectedElement, null, MPart.class); 4841 List<MPart> visibleParts = new ArrayList<>(parts.size()); 4842 for (MPart part : parts) { 4843 if (isVisible(selectedElement, part)) { 4844 visibleParts.add(part); 4845 } 4846 } 4847 4848 for (MPart part : visibleParts) { 4849 firePartVisible(part); 4850 } 4851 } 4852 } 4853 isVisible(MPerspective perspective, MUIElement element)4854 private boolean isVisible(MPerspective perspective, MUIElement element) { 4855 if (element == perspective) { 4856 return true; 4857 } else if (element.isVisible() && element.isToBeRendered()) { 4858 MElementContainer<?> parent = element.getParent(); 4859 if (parent instanceof MPartStack) { 4860 if (parent.getSelectedElement() == element) { 4861 return isVisible(perspective, parent); 4862 } 4863 } else if (parent == null) { 4864 if (element instanceof MTrimmedWindow) { 4865 return true; 4866 } 4867 MPlaceholder placeholder = element.getCurSharedRef(); 4868 return placeholder == null ? false : isVisible(perspective, placeholder); 4869 } else { 4870 return isVisible(perspective, parent); 4871 } 4872 } 4873 return false; 4874 } 4875 firePartActivated(MPart part)4876 private void firePartActivated(MPart part) { 4877 4878 Object client = part.getObject(); 4879 if (client instanceof CompatibilityPart) { 4880 final IWorkbenchPart workbenchPart = getWrappedPart((CompatibilityPart) client); 4881 if (workbenchPart == null) { 4882 return; 4883 } 4884 final IWorkbenchPartReference partReference = getReference(workbenchPart); 4885 if (partReference == null) { 4886 WorkbenchPlugin.log(new RuntimeException("Reference is null in firePartActivated: " + part)); //$NON-NLS-1$ 4887 return; 4888 } 4889 4890 for (final IPartListener listener : partListenerList) { 4891 SafeRunner.run(new SafeRunnable() { 4892 @Override 4893 public void run() throws Exception { 4894 listener.partActivated(workbenchPart); 4895 } 4896 }); 4897 } 4898 4899 for (final IPartListener2 listener : partListener2List) { 4900 SafeRunner.run(new SafeRunnable() { 4901 @Override 4902 public void run() throws Exception { 4903 listener.partActivated(partReference); 4904 } 4905 }); 4906 } 4907 } else if (client != null) { 4908 if (part.getTransientData().get(E4PartWrapper.E4_WRAPPER_KEY) instanceof E4PartWrapper) { 4909 IWorkbenchPart workbenchPart = (IWorkbenchPart) part.getTransientData() 4910 .get(E4PartWrapper.E4_WRAPPER_KEY); 4911 final IWorkbenchPartReference partReference = getReference(workbenchPart); 4912 4913 if (partReference != null) { 4914 for (final IPartListener listener : partListenerList) { 4915 SafeRunner.run(new SafeRunnable() { 4916 @Override 4917 public void run() throws Exception { 4918 listener.partActivated(workbenchPart); 4919 } 4920 }); 4921 } 4922 4923 for (final IPartListener2 listener : partListener2List) { 4924 SafeRunner.run(new SafeRunnable() { 4925 @Override 4926 public void run() throws Exception { 4927 listener.partActivated(partReference); 4928 } 4929 }); 4930 } 4931 } 4932 } 4933 } 4934 } 4935 firePartDeactivated(MPart part)4936 private void firePartDeactivated(MPart part) { 4937 Object client = part.getObject(); 4938 if (client instanceof CompatibilityPart) { 4939 final IWorkbenchPart workbenchPart = getWrappedPart((CompatibilityPart) client); 4940 if (workbenchPart == null) { 4941 return; 4942 } 4943 final IWorkbenchPartReference partReference = getReference(workbenchPart); 4944 4945 for (final IPartListener listener : partListenerList) { 4946 SafeRunner.run(new SafeRunnable() { 4947 @Override 4948 public void run() throws Exception { 4949 listener.partDeactivated(workbenchPart); 4950 } 4951 }); 4952 } 4953 4954 for (final IPartListener2 listener : partListener2List) { 4955 SafeRunner.run(new SafeRunnable() { 4956 @Override 4957 public void run() throws Exception { 4958 listener.partDeactivated(partReference); 4959 } 4960 }); 4961 } 4962 } else if (client != null) { 4963 if (part.getTransientData().get(E4PartWrapper.E4_WRAPPER_KEY) instanceof E4PartWrapper) { 4964 IWorkbenchPart workbenchPart = (IWorkbenchPart) part.getTransientData() 4965 .get(E4PartWrapper.E4_WRAPPER_KEY); 4966 final IWorkbenchPartReference partReference = getReference(workbenchPart); 4967 4968 if (partReference != null) { 4969 for (final IPartListener listener : partListenerList) { 4970 SafeRunner.run(new SafeRunnable() { 4971 @Override 4972 public void run() throws Exception { 4973 listener.partDeactivated(workbenchPart); 4974 } 4975 }); 4976 } 4977 4978 for (final IPartListener2 listener : partListener2List) { 4979 SafeRunner.run(new SafeRunnable() { 4980 @Override 4981 public void run() throws Exception { 4982 listener.partDeactivated(partReference); 4983 } 4984 }); 4985 } 4986 } 4987 } 4988 } 4989 } 4990 4991 /** 4992 * @param comPart e4 wrapper around {@link IWorkbenchPart} 4993 * @return can return null, in case {@link CompatibilityPart} was already 4994 * disposed 4995 */ getWrappedPart(CompatibilityPart comPart)4996 private IWorkbenchPart getWrappedPart(CompatibilityPart comPart) { 4997 IWorkbenchPart part = comPart.getPart(); 4998 if (part == null) { 4999 WorkbenchPlugin.log(new RuntimeException("Trying to access already disposed part: " //$NON-NLS-1$ 5000 + comPart)); 5001 } 5002 return part; 5003 } 5004 firePartOpened(CompatibilityPart compatibilityPart)5005 public void firePartOpened(CompatibilityPart compatibilityPart) { 5006 final IWorkbenchPart part = getWrappedPart(compatibilityPart); 5007 final IWorkbenchPartReference partReference = compatibilityPart.getReference(); 5008 5009 if (part != null) { 5010 SaveablesList saveablesList = (SaveablesList) getWorkbenchWindow() 5011 .getService(ISaveablesLifecycleListener.class); 5012 saveablesList.postOpen(part); 5013 for (final IPartListener listener : partListenerList) { 5014 SafeRunner.run(new SafeRunnable() { 5015 @Override 5016 public void run() throws Exception { 5017 listener.partOpened(part); 5018 } 5019 }); 5020 } 5021 } 5022 5023 for (final IPartListener2 listener : partListener2List) { 5024 SafeRunner.run(new SafeRunnable() { 5025 @Override 5026 public void run() throws Exception { 5027 listener.partOpened(partReference); 5028 } 5029 }); 5030 } 5031 5032 if (part instanceof IPageChangeProvider) { 5033 ((IPageChangeProvider) part).addPageChangedListener(pageChangedListener); 5034 } 5035 5036 if (compatibilityPart instanceof CompatibilityView) { 5037 legacyWindow.firePerspectiveChanged(this, getPerspective(), partReference, CHANGE_VIEW_SHOW); 5038 legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_VIEW_SHOW); 5039 } 5040 } 5041 firePartClosed(CompatibilityPart compatibilityPart)5042 public void firePartClosed(CompatibilityPart compatibilityPart) { 5043 final IWorkbenchPart part = getWrappedPart(compatibilityPart); 5044 final WorkbenchPartReference partReference = compatibilityPart.getReference(); 5045 MPart model = partReference.getModel(); 5046 5047 if (part != null) { 5048 SaveablesList modelManager = (SaveablesList) getWorkbenchWindow() 5049 .getService(ISaveablesLifecycleListener.class); 5050 Object postCloseInfo = modelManager.preCloseParts(Collections.singletonList(part), false, 5051 getWorkbenchWindow()); 5052 if (postCloseInfo != null) { 5053 modelManager.postClose(postCloseInfo); 5054 } 5055 5056 for (final IPartListener listener : partListenerList) { 5057 SafeRunner.run(new SafeRunnable() { 5058 @Override 5059 public void run() throws Exception { 5060 listener.partClosed(part); 5061 } 5062 }); 5063 } 5064 } 5065 5066 for (final IPartListener2 listener : partListener2List) { 5067 SafeRunner.run(new SafeRunnable() { 5068 @Override 5069 public void run() throws Exception { 5070 listener.partClosed(partReference); 5071 } 5072 }); 5073 } 5074 5075 if (part instanceof IViewPart) { 5076 viewReferences.remove(partReference); 5077 } else if (part != null) { 5078 editorReferences.remove(partReference); 5079 } else { 5080 // Whatever it was, try to cleanup the dirt 5081 viewReferences.remove(partReference); 5082 editorReferences.remove(partReference); 5083 } 5084 5085 for (int i = 0; i < activationList.size(); i++) { 5086 if (model == activationList.get(i)) { 5087 activationList.remove(i); 5088 break; 5089 } 5090 } 5091 5092 MPart activePart = partService.getActivePart(); 5093 if (activePart == null) { 5094 // unset active part/editor sources if no active part found 5095 updateActivePartSources(null); 5096 updateActiveEditorSources(null); 5097 } else if (part instanceof IEditorPart) { 5098 // an editor got closed, update information about active editor 5099 IEditorPart activeEditor = getActiveEditor(); 5100 if (activeEditor == null) { 5101 updateActiveEditorSources(activePart); 5102 } else { 5103 updateActiveEditorSources(findPart(activeEditor)); 5104 } 5105 } 5106 5107 if (part instanceof IPageChangeProvider) { 5108 ((IPageChangeProvider) part).removePageChangedListener(pageChangedListener); 5109 } 5110 5111 if (compatibilityPart instanceof CompatibilityView) { 5112 legacyWindow.firePerspectiveChanged(this, getPerspective(), partReference, CHANGE_VIEW_HIDE); 5113 legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_VIEW_HIDE); 5114 } 5115 } 5116 firePartBroughtToTop(MPart part)5117 private void firePartBroughtToTop(MPart part) { 5118 Object client = part.getObject(); 5119 if (client instanceof CompatibilityPart) { 5120 final IWorkbenchPart workbenchPart = getWrappedPart((CompatibilityPart) client); 5121 if (workbenchPart == null) { 5122 return; 5123 } 5124 final IWorkbenchPartReference partReference = getReference(workbenchPart); 5125 5126 for (final IPartListener listener : partListenerList) { 5127 SafeRunner.run(new SafeRunnable() { 5128 @Override 5129 public void run() throws Exception { 5130 listener.partBroughtToTop(workbenchPart); 5131 } 5132 }); 5133 } 5134 5135 for (final IPartListener2 listener : partListener2List) { 5136 SafeRunner.run(new SafeRunnable() { 5137 @Override 5138 public void run() throws Exception { 5139 listener.partBroughtToTop(partReference); 5140 } 5141 }); 5142 } 5143 } else { 5144 Integer val = partEvents.get(part); 5145 if (val == null) { 5146 partEvents.put(part, Integer.valueOf(FIRE_PART_BROUGHTTOTOP)); 5147 } else { 5148 partEvents.put(part, Integer.valueOf(val.intValue() | FIRE_PART_BROUGHTTOTOP)); 5149 } 5150 } 5151 } 5152 5153 private WeakHashMap<MPart, Integer> partEvents = new WeakHashMap<>(); 5154 private static final int FIRE_PART_VISIBLE = 0x1; 5155 private static final int FIRE_PART_BROUGHTTOTOP = 0x2; 5156 5157 private EventHandler firingHandler = event -> { 5158 Object element = event.getProperty(UIEvents.EventTags.ELEMENT); 5159 Object value = event.getProperty(UIEvents.EventTags.NEW_VALUE); 5160 if (value instanceof CompatibilityPart && element instanceof MPart) { 5161 Integer events = partEvents.remove(element); 5162 if (events != null) { 5163 int e = events.intValue(); 5164 if ((e & FIRE_PART_VISIBLE) == FIRE_PART_VISIBLE) { 5165 firePartVisible((MPart) element); 5166 } 5167 if ((e & FIRE_PART_BROUGHTTOTOP) == FIRE_PART_BROUGHTTOTOP) { 5168 firePartBroughtToTop((MPart) element); 5169 } 5170 } 5171 } 5172 }; 5173 5174 private EventHandler childrenHandler = event -> { 5175 Object changedObj = event.getProperty(UIEvents.EventTags.ELEMENT); 5176 5177 // ...in this window ? 5178 MUIElement changedElement = (MUIElement) changedObj; 5179 if (modelService.getTopLevelWindowFor(changedElement) != window) 5180 return; 5181 5182 if (UIEvents.isADD(event)) { 5183 for (Object o : UIEvents.asIterable(event, UIEvents.EventTags.NEW_VALUE)) { 5184 if (!(o instanceof MUIElement)) 5185 continue; 5186 5187 // We have to iterate through the new elements to see if any 5188 // contain (or are) MParts (e.g. we may have dragged a split 5189 // editor which contains two editors, both with EditorRefs) 5190 MUIElement element = (MUIElement) o; 5191 List<MPart> addedParts = modelService.findElements(element, null, MPart.class, null); 5192 for (MPart part : addedParts) { 5193 IWorkbenchPartReference ref = (IWorkbenchPartReference) part.getTransientData() 5194 .get(IWorkbenchPartReference.class.getName()); 5195 5196 // For now we only check for editors changing pages 5197 if (ref instanceof EditorReference && getEditorReference(part) == null) { 5198 addEditorReference((EditorReference) ref); 5199 } 5200 } 5201 } 5202 } 5203 }; 5204 5205 // FIXME: convert me to e4 events! firePartVisible(MPart part)5206 private void firePartVisible(MPart part) { 5207 Object client = part.getObject(); 5208 if (client instanceof CompatibilityPart) { 5209 IWorkbenchPart workbenchPart = getWrappedPart((CompatibilityPart) client); 5210 if (workbenchPart == null) { 5211 return; 5212 } 5213 final IWorkbenchPartReference partReference = getReference(workbenchPart); 5214 5215 for (final IPartListener2 listener : partListener2List) { 5216 SafeRunner.run(new SafeRunnable() { 5217 @Override 5218 public void run() throws Exception { 5219 listener.partVisible(partReference); 5220 } 5221 }); 5222 } 5223 } else { 5224 Integer val = partEvents.get(part); 5225 if (val == null) { 5226 partEvents.put(part, Integer.valueOf(FIRE_PART_VISIBLE)); 5227 } else { 5228 partEvents.put(part, Integer.valueOf(val.intValue() | FIRE_PART_VISIBLE)); 5229 } 5230 } 5231 } 5232 5233 // FIXME: convert me to e4 events! firePartHidden(MPart part)5234 public void firePartHidden(MPart part) { 5235 Object client = part.getObject(); 5236 if (client instanceof CompatibilityPart) { 5237 IWorkbenchPart workbenchPart = getWrappedPart((CompatibilityPart) client); 5238 if (workbenchPart == null) { 5239 return; 5240 } 5241 final IWorkbenchPartReference partReference = getReference(workbenchPart); 5242 5243 for (final IPartListener2 listener : partListener2List) { 5244 SafeRunner.run(new SafeRunnable() { 5245 @Override 5246 public void run() throws Exception { 5247 listener.partHidden(partReference); 5248 } 5249 }); 5250 } 5251 } 5252 } 5253 firePartInputChanged(final IWorkbenchPartReference partReference)5254 public void firePartInputChanged(final IWorkbenchPartReference partReference) { 5255 for (final IPartListener2 listener : partListener2List) { 5256 SafeRunner.run(new SafeRunnable() { 5257 @Override 5258 public void run() throws Exception { 5259 listener.partInputChanged(partReference); 5260 } 5261 }); 5262 } 5263 } 5264 5265 @Override getEditorReuseThreshold()5266 public int getEditorReuseThreshold() { 5267 IPreferenceStore store = WorkbenchPlugin.getDefault().getPreferenceStore(); 5268 return store.getInt(IPreferenceConstants.REUSE_EDITORS); 5269 } 5270 5271 @Override setEditorReuseThreshold(int openEditors)5272 public void setEditorReuseThreshold(int openEditors) { 5273 // this is an empty implementation in 3.x, see IPageLayout's 5274 // setEditorReuseThreshold 5275 } 5276 5277 /** 5278 * Opens an editor represented by the descriptor with the given input. 5279 * 5280 * @param fileEditorInput the input that the editor should open 5281 * @param editorDescriptor the descriptor of the editor to open 5282 * @param activate <code>true</code> if the editor should be activated, 5283 * <code>false</code> otherwise 5284 * @param editorState the previously saved state of the editor as a 5285 * memento, this may be <code>null</code> 5286 * @return the opened editor 5287 * @exception PartInitException if the editor could not be created or 5288 * initialized 5289 */ openEditorFromDescriptor(IEditorInput fileEditorInput, IEditorDescriptor editorDescriptor, final boolean activate, final IMemento editorState)5290 public IEditorPart openEditorFromDescriptor(IEditorInput fileEditorInput, IEditorDescriptor editorDescriptor, 5291 final boolean activate, final IMemento editorState) throws PartInitException { 5292 if (editorDescriptor.isOpenExternal()) { 5293 openExternalEditor((EditorDescriptor) editorDescriptor, fileEditorInput); 5294 return null; 5295 } 5296 return openEditor(fileEditorInput, editorDescriptor.getId(), activate, MATCH_INPUT, editorState, true); 5297 } 5298 5299 /** 5300 * Open a specific external editor on an file based on the descriptor. 5301 */ openExternalEditor(final EditorDescriptor desc, IEditorInput input)5302 private IEditorReference openExternalEditor(final EditorDescriptor desc, IEditorInput input) 5303 throws PartInitException { 5304 final CoreException ex[] = new CoreException[1]; 5305 5306 final IPathEditorInput pathInput = getPathEditorInput(input); 5307 if (pathInput != null && pathInput.getPath() != null) { 5308 BusyIndicator.showWhile(legacyWindow.getWorkbench().getDisplay(), () -> { 5309 try { 5310 if (desc.getLauncher() != null) { 5311 // open using launcher 5312 Object launcher = WorkbenchPlugin.createExtension(desc.getConfigurationElement(), 5313 IWorkbenchRegistryConstants.ATT_LAUNCHER); 5314 ((IEditorLauncher) launcher).open(pathInput.getPath()); 5315 } else { 5316 // open using command 5317 ExternalEditor oEditor = new ExternalEditor(pathInput.getPath(), desc); 5318 oEditor.open(); 5319 } 5320 } catch (CoreException e) { 5321 ex[0] = e; 5322 } 5323 }); 5324 } else { 5325 throw new PartInitException(NLS.bind(WorkbenchMessages.EditorManager_errorOpeningExternalEditor, 5326 desc.getFileName(), desc.getId())); 5327 } 5328 5329 if (ex[0] != null) { 5330 throw new PartInitException(NLS.bind(WorkbenchMessages.EditorManager_errorOpeningExternalEditor, 5331 desc.getFileName(), desc.getId()), ex[0]); 5332 } 5333 5334 recordEditor(input, desc); 5335 // we do not have an editor part for external editors 5336 return null; 5337 } 5338 getPathEditorInput(IEditorInput input)5339 private IPathEditorInput getPathEditorInput(IEditorInput input) { 5340 if (input instanceof IPathEditorInput) 5341 return (IPathEditorInput) input; 5342 return Adapters.adapt(input, IPathEditorInput.class); 5343 } 5344 5345 /** 5346 * Unzooms the shared area if there are no more rendered parts contained within 5347 * it. 5348 * 5349 * @see #unzoomSharedArea(MUIElement) 5350 */ unzoomSharedArea()5351 private void unzoomSharedArea() { 5352 MPerspective curPersp = getPerspectiveStack().getSelectedElement(); 5353 if (curPersp == null) 5354 return; 5355 5356 MPlaceholder eaPH = (MPlaceholder) modelService.find(IPageLayout.ID_EDITOR_AREA, curPersp); 5357 for (MPart part : modelService.findElements(eaPH, null, MPart.class, null)) { 5358 if (part.isToBeRendered()) { 5359 MPlaceholder placeholder = part.getCurSharedRef(); 5360 if (placeholder == null || placeholder.isToBeRendered()) { 5361 return; 5362 } 5363 } 5364 } 5365 5366 setPartState(eaPH, null); 5367 } 5368 5369 /** 5370 * Unzooms the shared area if the specified element is in the shared area. 5371 * 5372 * @param element the element to check if it is in the shared area 5373 * @see #unzoomSharedArea() 5374 */ unzoomSharedArea(MUIElement element)5375 private void unzoomSharedArea(MUIElement element) { 5376 if (modelService.getElementLocation(element) == EModelService.IN_SHARED_AREA) { 5377 unzoomSharedArea(); 5378 } 5379 } 5380 5381 /** 5382 * An event handler for listening to parts and placeholders being unrendered. 5383 */ 5384 private EventHandler referenceRemovalEventHandler = event -> { 5385 if (Boolean.TRUE.equals(event.getProperty(UIEvents.EventTags.NEW_VALUE))) { 5386 return; 5387 } 5388 5389 Object element = event.getProperty(UIEvents.EventTags.ELEMENT); 5390 if (element instanceof MPlaceholder) { 5391 MUIElement ref = ((MPlaceholder) element).getRef(); 5392 // a placeholder has been unrendered, check to see if the shared 5393 // area needs to be unzoomed 5394 unzoomSharedArea(ref); 5395 5396 if (ref instanceof MPart) { 5397 // find all placeholders for this part 5398 List<MPlaceholder> placeholders = modelService.findElements(window, ref.getElementId(), 5399 MPlaceholder.class, null, EModelService.IN_ANY_PERSPECTIVE | EModelService.IN_SHARED_AREA 5400 | EModelService.OUTSIDE_PERSPECTIVE); 5401 for (MPlaceholder placeholder : placeholders) { 5402 if (placeholder.getRef() == ref && placeholder.isToBeRendered()) { 5403 // if there's a rendered placeholder, return 5404 return; 5405 } 5406 } 5407 5408 // no rendered placeholders around, unsubscribe 5409 ViewReference reference1 = getViewReference((MPart) ref); 5410 if (reference1 != null) { 5411 reference1.unsubscribe(); 5412 } 5413 } 5414 } else if (element instanceof MPart) { 5415 MPart part = (MPart) element; 5416 // a part has been unrendered, check to see if the shared 5417 // area needs to be unzoomed 5418 unzoomSharedArea(part); 5419 5420 if (CompatibilityEditor.MODEL_ELEMENT_ID.equals(part.getElementId())) { 5421 EditorReference reference2 = getEditorReference(part); 5422 if (reference2 != null) { 5423 reference2.unsubscribe(); 5424 } 5425 } 5426 } 5427 }; 5428 getHiddenItems()5429 public String getHiddenItems() { 5430 MPerspective perspective = getCurrentPerspective(); 5431 if (perspective == null) 5432 return ""; //$NON-NLS-1$ 5433 5434 String result = perspective.getPersistedState().get(ModeledPageLayout.HIDDEN_ITEMS_KEY); 5435 if (result == null) 5436 return ""; //$NON-NLS-1$ 5437 5438 return result; 5439 } 5440 addHiddenItems(MPerspective perspective, String id)5441 public void addHiddenItems(MPerspective perspective, String id) { 5442 String hiddenIDs = perspective.getPersistedState().get(ModeledPageLayout.HIDDEN_ITEMS_KEY); 5443 if (hiddenIDs == null) 5444 hiddenIDs = ""; //$NON-NLS-1$ 5445 5446 String persistedID = id + ","; //$NON-NLS-1$ 5447 if (!hiddenIDs.contains(persistedID)) { 5448 hiddenIDs = hiddenIDs + persistedID; 5449 perspective.getPersistedState().put(ModeledPageLayout.HIDDEN_ITEMS_KEY, hiddenIDs); 5450 } 5451 } 5452 addHiddenItems(String id)5453 public void addHiddenItems(String id) { 5454 MPerspective perspective = getCurrentPerspective(); 5455 if (perspective == null) 5456 return; 5457 addHiddenItems(perspective, id); 5458 } 5459 removeHiddenItems(MPerspective perspective, String id)5460 public void removeHiddenItems(MPerspective perspective, String id) { 5461 String persistedID = id + ","; //$NON-NLS-1$ 5462 5463 String hiddenIDs = perspective.getPersistedState().get(ModeledPageLayout.HIDDEN_ITEMS_KEY); 5464 if (hiddenIDs == null) 5465 return; 5466 5467 String newValue = hiddenIDs.replaceFirst(persistedID, ""); //$NON-NLS-1$ 5468 if (hiddenIDs.length() != newValue.length()) { 5469 if (newValue.length() == 0) 5470 perspective.getPersistedState().remove(ModeledPageLayout.HIDDEN_ITEMS_KEY); 5471 else 5472 perspective.getPersistedState().put(ModeledPageLayout.HIDDEN_ITEMS_KEY, newValue); 5473 } 5474 } 5475 removeHiddenItems(String id)5476 public void removeHiddenItems(String id) { 5477 MPerspective perspective = getCurrentPerspective(); 5478 if (perspective == null) 5479 return; 5480 removeHiddenItems(perspective, id); 5481 } 5482 setNewShortcuts(List<String> wizards, String tagPrefix)5483 public void setNewShortcuts(List<String> wizards, String tagPrefix) { 5484 MPerspective persp = getCurrentPerspective(); 5485 if (persp == null) 5486 return; 5487 5488 List<String> existingNewWizards = new ArrayList<>(); 5489 for (String tag : persp.getTags()) { 5490 if (tag.contains(tagPrefix)) 5491 existingNewWizards.add(tag); 5492 } 5493 5494 List<String> newWizards = new ArrayList<>(wizards.size()); 5495 for (String wizardName : wizards) { 5496 newWizards.add(tagPrefix + wizardName); 5497 } 5498 5499 persp.getTags().removeAll(existingNewWizards); 5500 persp.getTags().addAll(newWizards); 5501 } 5502 5503 /** 5504 * 5505 */ resetToolBarLayout()5506 public void resetToolBarLayout() { 5507 ICoolBarManager2 mgr = (ICoolBarManager2) legacyWindow.getCoolBarManager2(); 5508 mgr.resetItemOrder(); 5509 } 5510 5511 /** 5512 * Call {@link #firePartDeactivated(MPart)} if the passed part is the currently 5513 * active part according to the part service. This method should only be called 5514 * in the case of workbench shutdown, where E4 does not fire deactivate 5515 * listeners on the active part. 5516 * 5517 * @param part 5518 */ firePartDeactivatedIfActive(MPart part)5519 public void firePartDeactivatedIfActive(MPart part) { 5520 if (partService.getActivePart() == part) { 5521 // At shutdown, e4 doesn't fire part deactivated on the active 5522 // part. 5523 firePartDeactivated(part); 5524 } 5525 } 5526 5527 /** 5528 * Add ToolItems for perspectives specified in "PERSPECTIVE_BAR_EXTRAS" 5529 */ createPerspectiveBarExtras()5530 private void createPerspectiveBarExtras() { 5531 String persps = PrefUtil.getAPIPreferenceStore() 5532 .getString(IWorkbenchPreferenceConstants.PERSPECTIVE_BAR_EXTRAS); 5533 // e3 allowed spaces and commas as separator 5534 String[] parts = persps.split("[, ]"); //$NON-NLS-1$ 5535 Set<String> perspSet = new LinkedHashSet<>(); 5536 for (String part : parts) { 5537 part = part.trim(); 5538 if (!part.isEmpty()) 5539 perspSet.add(part); 5540 } 5541 5542 for (String perspId : perspSet) { 5543 MPerspective persp = (MPerspective) modelService.find(perspId, window); 5544 if (persp != null) 5545 continue; // already in stack, i.e. has already been added above 5546 IPerspectiveDescriptor desc = getDescriptorFor(perspId); 5547 if (desc == null) 5548 continue; // this perspective does not exist 5549 persp = createPerspective(desc); 5550 persp.setLabel(desc.getLabel()); 5551 getPerspectiveStack().getChildren().add(persp); 5552 // "add" fires Event, causes creation of ToolItem on perspective bar 5553 } 5554 } 5555 getDescriptorFor(String id)5556 private IPerspectiveDescriptor getDescriptorFor(String id) { 5557 IPerspectiveRegistry perspectiveRegistry = getWorkbenchWindow().getWorkbench().getPerspectiveRegistry(); 5558 if (perspectiveRegistry instanceof PerspectiveRegistry) { 5559 return ((PerspectiveRegistry) perspectiveRegistry).findPerspectiveWithId(id, false); 5560 } 5561 5562 return perspectiveRegistry.findPerspectiveWithId(id); 5563 } 5564 5565 } 5566