| /******************************************************************************* |
| * Copyright (c) 2000, 2016 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Christian Janz - <christian.janz@gmail.com> Fix for Bug 385592 |
| * Marc-Andre Laperle (Ericsson) - Fix for Bug 413590 |
| * Lars Vogel <Lars.Vogel@vogella.com> - Bug 431340, 431348, 426535, 433234, 431868, 472654 |
| * Cornel Izbasa <cizbasa@info.uvt.ro> - Bug 442214 |
| * Andrey Loskutov <loskutov@gmx.de> - Bug 411639, 372799, 466230 |
| * Dirk Fauth <dirk.fauth@googlemail.com> - Bug 473063 |
| *******************************************************************************/ |
| |
| package org.eclipse.ui.internal; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.StringReader; |
| import java.io.StringWriter; |
| import java.net.MalformedURLException; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.text.MessageFormat; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.LinkedHashSet; |
| import java.util.List; |
| import java.util.ListIterator; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.WeakHashMap; |
| import javax.annotation.PostConstruct; |
| import javax.annotation.PreDestroy; |
| import javax.inject.Inject; |
| import org.eclipse.core.runtime.Adapters; |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.ListenerList; |
| import org.eclipse.core.runtime.SafeRunner; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker; |
| import org.eclipse.e4.core.contexts.ContextInjectionFactory; |
| import org.eclipse.e4.core.contexts.IEclipseContext; |
| import org.eclipse.e4.core.di.annotations.Optional; |
| import org.eclipse.e4.core.services.events.IEventBroker; |
| import org.eclipse.e4.ui.di.UIEventTopic; |
| import org.eclipse.e4.ui.internal.workbench.ModelServiceImpl; |
| import org.eclipse.e4.ui.internal.workbench.PartServiceImpl; |
| import org.eclipse.e4.ui.model.application.MApplication; |
| import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor; |
| import org.eclipse.e4.ui.model.application.ui.MElementContainer; |
| import org.eclipse.e4.ui.model.application.ui.MGenericStack; |
| import org.eclipse.e4.ui.model.application.ui.MUIElement; |
| import org.eclipse.e4.ui.model.application.ui.advanced.MArea; |
| import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective; |
| import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack; |
| import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder; |
| import org.eclipse.e4.ui.model.application.ui.basic.MPart; |
| import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer; |
| import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement; |
| import org.eclipse.e4.ui.model.application.ui.basic.MPartStack; |
| import org.eclipse.e4.ui.model.application.ui.basic.MStackElement; |
| import org.eclipse.e4.ui.model.application.ui.basic.MTrimElement; |
| import org.eclipse.e4.ui.model.application.ui.basic.MWindow; |
| import org.eclipse.e4.ui.model.application.ui.basic.MWindowElement; |
| import org.eclipse.e4.ui.model.application.ui.menu.MToolControl; |
| import org.eclipse.e4.ui.workbench.IPresentationEngine; |
| import org.eclipse.e4.ui.workbench.UIEvents; |
| import org.eclipse.e4.ui.workbench.UIEvents.EventTags; |
| import org.eclipse.e4.ui.workbench.modeling.EModelService; |
| import org.eclipse.e4.ui.workbench.modeling.EPartService; |
| import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.jface.dialogs.DialogSettings; |
| import org.eclipse.jface.dialogs.IDialogSettings; |
| import org.eclipse.jface.dialogs.IPageChangeProvider; |
| import org.eclipse.jface.dialogs.IPageChangedListener; |
| import org.eclipse.jface.dialogs.PageChangedEvent; |
| import org.eclipse.jface.internal.provisional.action.ICoolBarManager2; |
| import org.eclipse.jface.operation.IRunnableContext; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| import org.eclipse.jface.util.SafeRunnable; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.ISelectionProvider; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.custom.BusyIndicator; |
| import org.eclipse.swt.dnd.DND; |
| import org.eclipse.swt.dnd.DropTarget; |
| import org.eclipse.swt.dnd.DropTargetListener; |
| import org.eclipse.swt.program.Program; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.IActionBars; |
| import org.eclipse.ui.IEditorDescriptor; |
| import org.eclipse.ui.IEditorInput; |
| import org.eclipse.ui.IEditorLauncher; |
| import org.eclipse.ui.IEditorMatchingStrategy; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.IEditorReference; |
| import org.eclipse.ui.IEditorRegistry; |
| import org.eclipse.ui.IMemento; |
| import org.eclipse.ui.INavigationHistory; |
| import org.eclipse.ui.IPageLayout; |
| import org.eclipse.ui.IPartListener; |
| import org.eclipse.ui.IPartListener2; |
| import org.eclipse.ui.IPathEditorInput; |
| import org.eclipse.ui.IPersistableEditor; |
| import org.eclipse.ui.IPersistableElement; |
| import org.eclipse.ui.IPerspectiveDescriptor; |
| import org.eclipse.ui.IPerspectiveFactory; |
| import org.eclipse.ui.IPerspectiveRegistry; |
| import org.eclipse.ui.IReusableEditor; |
| import org.eclipse.ui.ISaveablePart; |
| import org.eclipse.ui.ISaveablePart2; |
| import org.eclipse.ui.ISaveablesLifecycleListener; |
| import org.eclipse.ui.ISaveablesSource; |
| import org.eclipse.ui.ISelectionListener; |
| import org.eclipse.ui.ISelectionService; |
| import org.eclipse.ui.IShowEditorInput; |
| import org.eclipse.ui.ISources; |
| import org.eclipse.ui.IViewPart; |
| import org.eclipse.ui.IViewReference; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.IWorkbenchPart; |
| import org.eclipse.ui.IWorkbenchPartReference; |
| import org.eclipse.ui.IWorkbenchPartSite; |
| import org.eclipse.ui.IWorkbenchPreferenceConstants; |
| import org.eclipse.ui.IWorkbenchWindow; |
| import org.eclipse.ui.IWorkingSet; |
| import org.eclipse.ui.IWorkingSetManager; |
| import org.eclipse.ui.MultiPartInitException; |
| import org.eclipse.ui.PartInitException; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.Saveable; |
| import org.eclipse.ui.WorkbenchException; |
| import org.eclipse.ui.XMLMemento; |
| import org.eclipse.ui.contexts.IContextService; |
| import org.eclipse.ui.dialogs.EditorSelectionDialog; |
| import org.eclipse.ui.internal.dialogs.cpd.CustomizePerspectiveDialog; |
| import org.eclipse.ui.internal.e4.compatibility.CompatibilityEditor; |
| import org.eclipse.ui.internal.e4.compatibility.CompatibilityPart; |
| import org.eclipse.ui.internal.e4.compatibility.CompatibilityView; |
| import org.eclipse.ui.internal.e4.compatibility.E4Util; |
| import org.eclipse.ui.internal.e4.compatibility.ModeledPageLayout; |
| import org.eclipse.ui.internal.e4.compatibility.SelectionService; |
| import org.eclipse.ui.internal.menus.MenuHelper; |
| import org.eclipse.ui.internal.misc.ExternalEditor; |
| import org.eclipse.ui.internal.misc.StatusUtil; |
| import org.eclipse.ui.internal.misc.UIListenerLogging; |
| import org.eclipse.ui.internal.progress.ProgressManagerUtil; |
| import org.eclipse.ui.internal.registry.ActionSetRegistry; |
| import org.eclipse.ui.internal.registry.EditorDescriptor; |
| import org.eclipse.ui.internal.registry.IActionSetDescriptor; |
| import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants; |
| import org.eclipse.ui.internal.registry.PerspectiveDescriptor; |
| import org.eclipse.ui.internal.registry.PerspectiveRegistry; |
| import org.eclipse.ui.internal.registry.UIExtensionTracker; |
| import org.eclipse.ui.internal.registry.ViewDescriptor; |
| import org.eclipse.ui.internal.tweaklets.TabBehaviour; |
| import org.eclipse.ui.internal.tweaklets.Tweaklets; |
| import org.eclipse.ui.internal.util.PrefUtil; |
| import org.eclipse.ui.internal.util.Util; |
| import org.eclipse.ui.model.IWorkbenchAdapter; |
| import org.eclipse.ui.part.IShowInSource; |
| import org.eclipse.ui.part.ShowInContext; |
| import org.eclipse.ui.statushandlers.StatusManager; |
| import org.eclipse.ui.views.IStickyViewDescriptor; |
| import org.eclipse.ui.views.IViewDescriptor; |
| import org.osgi.service.event.Event; |
| import org.osgi.service.event.EventHandler; |
| |
| /** |
| * A collection of views and editors in a workbench. |
| */ |
| public class WorkbenchPage implements IWorkbenchPage { |
| |
| private static final String ATT_AGGREGATE_WORKING_SET_ID = "aggregateWorkingSetId"; //$NON-NLS-1$ |
| |
| private static final int WINDOW_SCOPE = EModelService.OUTSIDE_PERSPECTIVE |
| | EModelService.IN_ANY_PERSPECTIVE | EModelService.IN_SHARED_AREA; |
| |
| class E4PartListener implements org.eclipse.e4.ui.workbench.modeling.IPartListener { |
| |
| @Override |
| public void partActivated(MPart part) { |
| // update the workbench window's current selection with the active |
| // part's selection |
| IWorkbenchPart workbenchPart = getWorkbenchPart(part); |
| selectionService.updateSelection(workbenchPart); |
| |
| updateActivations(part); |
| firePartActivated(part); |
| selectionService.notifyListeners(workbenchPart); |
| } |
| |
| @Override |
| public void partBroughtToTop(MPart part) { |
| updateBroughtToTop(part); |
| firePartBroughtToTop(part); |
| } |
| |
| @Override |
| public void partDeactivated(MPart part) { |
| firePartDeactivated(part); |
| |
| Object client = part.getObject(); |
| if (client instanceof CompatibilityPart) { |
| CompatibilityPart compatibilityPart = (CompatibilityPart) client; |
| IWorkbenchPartSite site = compatibilityPart.getPart().getSite(); |
| // if it's an editor, we only want to disable the actions |
| ((PartSite) site).deactivateActionBars(site instanceof ViewSite); |
| } |
| |
| WorkbenchWindow wwindow = (WorkbenchWindow) getWorkbenchWindow(); |
| if (!wwindow.isClosing()) { |
| wwindow.getStatusLineManager().update(false); |
| } |
| } |
| |
| @Override |
| public void partHidden(MPart part) { |
| firePartHidden(part); |
| } |
| |
| @Override |
| public void partVisible(MPart part) { |
| firePartVisible(part); |
| } |
| } |
| |
| ArrayList<MPart> activationList = new ArrayList<>(); |
| |
| /** |
| * Cached perspective stack for this workbench page. |
| */ |
| private MPerspectiveStack _perspectiveStack; |
| |
| /** Ids of parts used as Show In targets, maintained in MRU order */ |
| private List<String> mruShowInPartIds = new ArrayList<>(); |
| |
| /** |
| * Deactivate the last editor's action bars if another type of editor has // |
| * * been activated. |
| * |
| * @param part |
| * the part that is being activated |
| */ |
| private void deactivateLastEditor(MPart part) { |
| Object client = part.getObject(); |
| // we only care if the currently activated part is an editor |
| if (client instanceof CompatibilityEditor) { |
| // find another editor that was last activated |
| for (MPart previouslyActive : activationList) { |
| if (previouslyActive != part) { |
| Object object = previouslyActive.getObject(); |
| if (object instanceof CompatibilityEditor) { |
| EditorSite site = (EditorSite) ((CompatibilityEditor) object).getPart() |
| .getSite(); |
| String lastId = site.getId(); |
| String activeId = ((CompatibilityEditor) client).getPart().getSite() |
| .getId(); |
| // if not the same, hide the other editor's action bars |
| if (lastId != null && !lastId.equals(activeId)) { |
| site.deactivateActionBars(true); |
| } |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| private void updateActivations(MPart part) { |
| if (activationList.size() > 1) { |
| deactivateLastEditor(part); |
| } |
| |
| activationList.remove(part); |
| activationList.add(0, part); |
| updateActivePartSources(part); |
| updateActiveEditorSources(part); |
| |
| Object client = part.getObject(); |
| if (client instanceof CompatibilityPart) { |
| IWorkbenchPart workbenchPart = ((CompatibilityPart) client).getPart(); |
| PartSite site = (PartSite) workbenchPart.getSite(); |
| site.activateActionBars(true); |
| |
| IActionBars actionBars = site.getActionBars(); |
| if (actionBars instanceof EditorActionBars) { |
| ((EditorActionBars) actionBars).partChanged(workbenchPart); |
| } |
| } |
| |
| ((WorkbenchWindow) getWorkbenchWindow()).getStatusLineManager().update(false); |
| |
| IWorkbenchPart workbenchPart = getWorkbenchPart(part); |
| actionSwitcher.updateActivePart(workbenchPart); |
| } |
| |
| private void updateActivePartSources(MPart part) { |
| IWorkbenchPart workbenchPart = getWorkbenchPart(part); |
| if (workbenchPart == null) { |
| window.getContext().set(ISources.ACTIVE_PART_NAME, null); |
| window.getContext().set(ISources.ACTIVE_PART_ID_NAME, null); |
| window.getContext().set(ISources.ACTIVE_SITE_NAME, null); |
| } else { |
| window.getContext().set(ISources.ACTIVE_PART_NAME, workbenchPart); |
| window.getContext().set(ISources.ACTIVE_PART_ID_NAME, workbenchPart.getSite().getId()); |
| window.getContext().set(ISources.ACTIVE_SITE_NAME, workbenchPart.getSite()); |
| } |
| |
| } |
| |
| private void updateActionSets(Perspective oldPersp, Perspective newPersp) { |
| // Update action sets |
| |
| IContextService service = legacyWindow.getService(IContextService.class); |
| try { |
| service.deferUpdates(true); |
| if (newPersp != null) { |
| List<IActionSetDescriptor> newAlwaysOn = newPersp.getAlwaysOnActionSets(); |
| for (int i = 0; i < newAlwaysOn.size(); i++) { |
| IActionSetDescriptor descriptor = newAlwaysOn.get(i); |
| |
| actionSets.showAction(descriptor); |
| } |
| |
| List<IActionSetDescriptor> newAlwaysOff = newPersp.getAlwaysOffActionSets(); |
| for (int i = 0; i < newAlwaysOff.size(); i++) { |
| IActionSetDescriptor descriptor = newAlwaysOff.get(i); |
| |
| actionSets.maskAction(descriptor); |
| } |
| } |
| |
| if (oldPersp != null) { |
| List<IActionSetDescriptor> oldAlwaysOn = oldPersp.getAlwaysOnActionSets(); |
| for (int i = 0; i < oldAlwaysOn.size(); i++) { |
| IActionSetDescriptor descriptor = oldAlwaysOn.get(i); |
| |
| actionSets.hideAction(descriptor); |
| } |
| |
| List<IActionSetDescriptor> oldAlwaysOff = oldPersp.getAlwaysOffActionSets(); |
| for (int i = 0; i < oldAlwaysOff.size(); i++) { |
| IActionSetDescriptor descriptor = oldAlwaysOff.get(i); |
| |
| actionSets.unmaskAction(descriptor); |
| } |
| } |
| } finally { |
| service.deferUpdates(false); |
| } |
| } |
| |
| private IWorkbenchPart getWorkbenchPart(MPart part) { |
| if (part != null) { |
| Object clientObject = part.getObject(); |
| if (clientObject instanceof CompatibilityPart) { |
| return ((CompatibilityPart) clientObject).getPart(); |
| } else if (clientObject != null) { |
| if (part.getTransientData().get(E4PartWrapper.E4_WRAPPER_KEY) instanceof E4PartWrapper) { |
| return (IWorkbenchPart) part.getTransientData().get( |
| E4PartWrapper.E4_WRAPPER_KEY); |
| } |
| |
| ViewReference viewReference = getViewReference(part); |
| if (viewReference != null) { |
| E4PartWrapper legacyPart = E4PartWrapper.getE4PartWrapper(part); |
| try { |
| viewReference.initialize(legacyPart); |
| } catch (PartInitException e) { |
| WorkbenchPlugin.log(e); |
| } |
| part.getTransientData().put(E4PartWrapper.E4_WRAPPER_KEY, legacyPart); |
| return legacyPart; |
| } |
| } |
| } |
| return null; |
| } |
| |
| private void updateActiveEditorSources(MPart part) { |
| IEditorPart editor = getEditor(part); |
| window.getContext().set(ISources.ACTIVE_EDITOR_ID_NAME, |
| editor == null ? null : editor.getSite().getId()); |
| window.getContext().set(ISources.ACTIVE_EDITOR_NAME, editor); |
| window.getContext().set(ISources.ACTIVE_EDITOR_INPUT_NAME, |
| editor == null ? null : editor.getEditorInput()); |
| |
| if (editor != null) { |
| navigationHistory.markEditor(editor); |
| } |
| actionSwitcher.updateTopEditor(editor); |
| } |
| |
| public void updateShowInSources(MPart part) { |
| |
| IWorkbenchPart workbenchPart = getWorkbenchPart(part); |
| ShowInContext context = getContext(workbenchPart); |
| if (context != null) { |
| window.getContext().set(ISources.SHOW_IN_INPUT, context.getInput()); |
| window.getContext().set(ISources.SHOW_IN_SELECTION, context.getSelection()); |
| } |
| } |
| |
| private IShowInSource getShowInSource(IWorkbenchPart sourcePart) { |
| return Adapters.adapt(sourcePart, IShowInSource.class); |
| } |
| |
| private ShowInContext getContext(IWorkbenchPart sourcePart) { |
| IShowInSource source = getShowInSource(sourcePart); |
| if (source != null) { |
| ShowInContext context = source.getShowInContext(); |
| if (context != null) { |
| return context; |
| } |
| } else if (sourcePart instanceof IEditorPart) { |
| Object input = ((IEditorPart) sourcePart).getEditorInput(); |
| ISelectionProvider sp = sourcePart.getSite().getSelectionProvider(); |
| ISelection sel = sp == null ? null : sp.getSelection(); |
| return new ShowInContext(input, sel); |
| } |
| return null; |
| } |
| |
| private IEditorPart getEditor(MPart part) { |
| if (part != null) { |
| Object clientObject = part.getObject(); |
| if (clientObject instanceof CompatibilityEditor) { |
| return ((CompatibilityEditor) clientObject).getEditor(); |
| } |
| } |
| return getActiveEditor(); |
| } |
| |
| private void updateBroughtToTop(MPart part) { |
| updateActiveEditorSources(part); |
| IWorkbenchPart workbenchPart = getWorkbenchPart(part); |
| if (workbenchPart instanceof IEditorPart) { |
| navigationHistory.markEditor((IEditorPart) workbenchPart); |
| } |
| |
| MElementContainer<?> parent = part.getParent(); |
| if (parent == null) { |
| MPlaceholder placeholder = part.getCurSharedRef(); |
| if (placeholder == null) { |
| return; |
| } |
| |
| parent = placeholder.getParent(); |
| } |
| |
| if (parent instanceof MPartStack) { |
| int newIndex = lastIndexOfContainer(parent); |
| // New index can be -1 if there is no last index |
| if (newIndex >= 0 && part == activationList.get(newIndex)) { |
| return; |
| } |
| activationList.remove(part); |
| if (newIndex >= 0 && newIndex < activationList.size() - 1) { |
| activationList.add(newIndex, part); |
| } else { |
| activationList.add(part); |
| } |
| } |
| } |
| |
| private int lastIndexOfContainer(MElementContainer<?> parent) { |
| for (int i = 0; i < activationList.size(); i++) { |
| MPart mPart = activationList.get(i); |
| MElementContainer<MUIElement> container = mPart.getParent(); |
| if (container == parent) { |
| return i; |
| } else if (container == null) { |
| MPlaceholder placeholder = mPart.getCurSharedRef(); |
| if (placeholder != null && placeholder.getParent() == parent) { |
| return i; |
| } |
| } |
| } |
| return -1; |
| } |
| |
| private List<ViewReference> viewReferences = new ArrayList<>(); |
| private List<EditorReference> editorReferences = new ArrayList<>(); |
| |
| private List<IPerspectiveDescriptor> sortedPerspectives = new ArrayList<>(); |
| |
| private ListenerList<IPartListener> partListenerList = new ListenerList<>(); |
| private ListenerList<IPartListener2> partListener2List = new ListenerList<>(); |
| |
| /** |
| * A listener that forwards page change events to our part listeners. |
| */ |
| private IPageChangedListener pageChangedListener = new IPageChangedListener() { |
| @Override |
| public void pageChanged(final PageChangedEvent event) { |
| for (final IPartListener2 listener : partListener2List) { |
| if (listener instanceof IPageChangedListener) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| ((IPageChangedListener) listener).pageChanged(event); |
| } |
| }); |
| } |
| } |
| } |
| }; |
| |
| private E4PartListener e4PartListener = new E4PartListener(); |
| |
| protected WorkbenchWindow legacyWindow; |
| |
| private IAdaptable input; |
| |
| private IWorkingSet workingSet; |
| |
| private AggregateWorkingSet aggregateWorkingSet; |
| |
| private Composite composite; |
| |
| private ListenerList<IPropertyChangeListener> propertyChangeListeners = new ListenerList<>(); |
| |
| private IActionBars actionBars; |
| |
| private ActionSetManager actionSets; |
| |
| private NavigationHistory navigationHistory = new NavigationHistory(this); |
| |
| |
| /** |
| * If we're in the process of activating a part, this points to the new part. |
| * Otherwise, this is null. |
| */ |
| private IWorkbenchPartReference partBeingActivated = null; |
| |
| |
| |
| private IPropertyChangeListener workingSetPropertyChangeListener = new IPropertyChangeListener() { |
| /* |
| * Remove the working set from the page if the working set is deleted. |
| */ |
| @Override |
| public void propertyChange(PropertyChangeEvent event) { |
| String property = event.getProperty(); |
| if (IWorkingSetManager.CHANGE_WORKING_SET_REMOVE.equals(property)) { |
| if(event.getOldValue().equals(workingSet)) { |
| setWorkingSet(null); |
| } |
| |
| // room for optimization here |
| List<IWorkingSet> newList = new ArrayList<>(Arrays.asList(workingSets)); |
| if (newList.remove(event.getOldValue())) { |
| setWorkingSets(newList.toArray(new IWorkingSet[newList.size()])); |
| } |
| } |
| } |
| }; |
| |
| private ActionSwitcher actionSwitcher = new ActionSwitcher(); |
| |
| private IExtensionTracker tracker; |
| |
| // Deferral count... delays disposing parts and sending certain events if nonzero |
| private int deferCount = 0; |
| |
| |
| private IWorkingSet[] workingSets = new IWorkingSet[0]; |
| private String aggregateWorkingSetId; |
| |
| // determines if a prompt is shown when opening large files |
| private long maxFileSize = 0; |
| private boolean checkDocumentSize; |
| |
| /** |
| * Manages editor contributions and action set part associations. |
| */ |
| private class ActionSwitcher { |
| private IWorkbenchPart activePart; |
| |
| private IEditorPart topEditor; |
| |
| private List<IActionSetDescriptor> oldActionSets = new ArrayList<>(); |
| |
| /** |
| * Updates the contributions given the new part as the active part. |
| * |
| * @param newPart |
| * the new active part, may be <code>null</code> |
| */ |
| public void updateActivePart(IWorkbenchPart newPart) { |
| if (activePart == newPart) { |
| return; |
| } |
| |
| boolean isNewPartAnEditor = newPart instanceof IEditorPart; |
| if (isNewPartAnEditor) { |
| String oldId = null; |
| if (topEditor != null) { |
| oldId = topEditor.getSite().getId(); |
| } |
| String newId = newPart.getSite().getId(); |
| |
| // if the active part is an editor and the new editor |
| // is the same kind of editor, then we don't have to do |
| // anything |
| if (activePart == topEditor && newId.equals(oldId)) { |
| activePart = newPart; |
| topEditor = (IEditorPart) newPart; |
| return; |
| } |
| |
| // remove the contributions of the old editor |
| // if it is a different kind of editor |
| if (oldId != null && !oldId.equals(newId)) { |
| deactivateContributions(topEditor, true); |
| } |
| |
| // if a view was the active part, disable its contributions |
| if (activePart != null && activePart != topEditor) { |
| deactivateContributions(activePart, true); |
| } |
| |
| // show (and enable) the contributions of the new editor |
| // if it is a different kind of editor or if the |
| // old active part was a view |
| if (!newId.equals(oldId) || activePart != topEditor) { |
| activateContributions(newPart, true); |
| } |
| |
| } else if (newPart == null) { |
| if (activePart != null) { |
| // remove all contributions |
| deactivateContributions(activePart, true); |
| } |
| } else { |
| // new part is a view |
| |
| // if old active part is a view, remove all contributions, |
| // but if old part is an editor only disable |
| if (activePart != null) { |
| deactivateContributions(activePart, activePart instanceof IViewPart); |
| } |
| |
| activateContributions(newPart, true); |
| } |
| |
| List<IActionSetDescriptor> newActionSets = null; |
| if (isNewPartAnEditor || (activePart == topEditor && newPart == null)) { |
| newActionSets = calculateActionSets(newPart, null); |
| } else { |
| newActionSets = calculateActionSets(newPart, topEditor); |
| } |
| |
| if (!updateActionSets(newActionSets)) { |
| updateActionBars(); |
| } |
| |
| if (isNewPartAnEditor) { |
| topEditor = (IEditorPart) newPart; |
| } else if (activePart == topEditor && newPart == null) { |
| // since we removed all the contributions, we clear the top |
| // editor |
| topEditor = null; |
| } |
| |
| activePart = newPart; |
| } |
| |
| /** |
| * Updates the contributions given the new part as the topEditor. |
| * |
| * @param newEditor |
| * the new top editor, may be <code>null</code> |
| */ |
| public void updateTopEditor(IEditorPart newEditor) { |
| if (topEditor == newEditor) { |
| return; |
| } |
| |
| if (activePart == topEditor) { |
| updateActivePart(newEditor); |
| return; |
| } |
| |
| String oldId = null; |
| if (topEditor != null) { |
| oldId = topEditor.getSite().getId(); |
| } |
| String newId = null; |
| if (newEditor != null) { |
| newId = newEditor.getSite().getId(); |
| } |
| if (oldId == null ? newId == null : oldId.equals(newId)) { |
| // we don't have to change anything |
| topEditor = newEditor; |
| return; |
| } |
| |
| // Remove the contributions of the old editor |
| if (topEditor != null) { |
| deactivateContributions(topEditor, true); |
| } |
| |
| // Show (disabled) the contributions of the new editor |
| if (newEditor != null) { |
| activateContributions(newEditor, false); |
| } |
| |
| List<IActionSetDescriptor> newActionSets = calculateActionSets(activePart, newEditor); |
| if (!updateActionSets(newActionSets)) { |
| updateActionBars(); |
| } |
| |
| topEditor = newEditor; |
| } |
| |
| /** |
| * Activates the contributions of the given part. If <code>enable</code> |
| * is <code>true</code> the contributions are visible and enabled, |
| * otherwise they are disabled. |
| * |
| * @param part |
| * the part whose contributions are to be activated |
| * @param enable |
| * <code>true</code> the contributions are to be enabled, not |
| * just visible. |
| */ |
| private void activateContributions(IWorkbenchPart part, boolean enable) { |
| PartSite site = (PartSite) part.getSite(); |
| site.activateActionBars(enable); |
| } |
| |
| /** |
| * Deactivates the contributions of the given part. If |
| * <code>remove</code> is <code>true</code> the contributions are |
| * removed, otherwise they are disabled. |
| * |
| * @param part |
| * the part whose contributions are to be deactivated |
| * @param remove |
| * <code>true</code> the contributions are to be removed, not |
| * just disabled. |
| */ |
| private void deactivateContributions(IWorkbenchPart part, boolean remove) { |
| PartSite site = (PartSite) part.getSite(); |
| site.deactivateActionBars(remove); |
| } |
| |
| /** |
| * Calculates the action sets to show for the given part and editor |
| * |
| * @param part |
| * the active part, may be <code>null</code> |
| * @param editor |
| * the current editor, may be <code>null</code>, may be the |
| * active part |
| * @return the new action sets |
| */ |
| private List<IActionSetDescriptor> calculateActionSets(IWorkbenchPart part, |
| IEditorPart editor) { |
| List<IActionSetDescriptor> newActionSets = new ArrayList<>(); |
| if (part != null) { |
| IActionSetDescriptor[] partActionSets = WorkbenchPlugin.getDefault() |
| .getActionSetRegistry().getActionSetsFor(part.getSite().getId()); |
| for (IActionSetDescriptor partActionSetDescriptor : partActionSets) { |
| newActionSets.add(partActionSetDescriptor); |
| } |
| } |
| if (editor != null && editor != part) { |
| IActionSetDescriptor[] editorActionSets = WorkbenchPlugin.getDefault() |
| .getActionSetRegistry().getActionSetsFor(editor.getSite().getId()); |
| for (IActionSetDescriptor editorActionSetDescriptor : editorActionSets) { |
| newActionSets.add(editorActionSetDescriptor); |
| } |
| } |
| return newActionSets; |
| } |
| |
| /** |
| * Updates the actions we are showing for the active part and current |
| * editor. |
| * |
| * @param newActionSets |
| * the action sets to show |
| * @return <code>true</code> if the action sets changed |
| */ |
| private boolean updateActionSets(List<IActionSetDescriptor> newActionSets) { |
| if (oldActionSets.equals(newActionSets)) { |
| return false; |
| } |
| |
| IContextService service = legacyWindow |
| .getService(IContextService.class); |
| try { |
| service.deferUpdates(true); |
| |
| // show the new |
| for (int i = 0; i < newActionSets.size(); i++) { |
| actionSets.showAction(newActionSets.get(i)); |
| } |
| |
| // hide the old |
| for (int i = 0; i < oldActionSets.size(); i++) { |
| actionSets.hideAction(oldActionSets.get(i)); |
| } |
| |
| oldActionSets = newActionSets; |
| |
| } finally { |
| service.deferUpdates(false); |
| } |
| Perspective persp = getActivePerspective(); |
| if (persp == null) { |
| return false; |
| } |
| |
| legacyWindow.updateActionSets(); // this calls updateActionBars |
| legacyWindow.firePerspectiveChanged(WorkbenchPage.this, getPerspective(), |
| CHANGE_ACTION_SET_SHOW); |
| return true; |
| } |
| |
| } |
| |
| private EPartService partService; |
| |
| private SelectionService selectionService; |
| |
| private MApplication application; |
| |
| private MWindow window; |
| |
| private EModelService modelService; |
| |
| private IEventBroker broker; |
| |
| /** |
| * An event handler that listens for an MArea's widget being set so that we |
| * can install DND support into its control. |
| */ |
| private EventHandler widgetHandler = new EventHandler() { |
| @Override |
| public void handleEvent(Event event) { |
| Object element = event.getProperty(UIEvents.EventTags.ELEMENT); |
| Object newValue = event.getProperty(UIEvents.EventTags.NEW_VALUE); |
| |
| if (element instanceof MArea) { |
| // If it's an MArea in this window install the DND handling |
| if (modelService.findElements(window, null, MArea.class, null).contains(element)) { |
| if (newValue instanceof Control) { |
| installAreaDropSupport((Control) newValue); |
| } |
| } |
| } else if (element instanceof MPart && newValue == null) { |
| // If it's a 'e4' part then remove the reference for it |
| MPart changedPart = (MPart) element; |
| Object impl = changedPart.getObject(); |
| if (impl != null && !(impl instanceof CompatibilityPart)) { |
| EditorReference eRef = getEditorReference(changedPart); |
| if (eRef != null) |
| editorReferences.remove(eRef); |
| ViewReference vRef = getViewReference(changedPart); |
| if (vRef != null) |
| viewReferences.remove(vRef); |
| } |
| } |
| } |
| }; |
| |
| @Inject |
| @Optional |
| private void handleMinimizedStacks( |
| @UIEventTopic(UIEvents.ApplicationElement.TOPIC_TAGS) Event event) { |
| Object changedObj = event.getProperty(EventTags.ELEMENT); |
| |
| if (!(changedObj instanceof MToolControl)) |
| return; |
| |
| final MToolControl minimizedStack = (MToolControl) changedObj; |
| |
| // Note: The non-API type TrimStack is not imported to avoid |
| // https://bugs.eclipse.org/435521 |
| if (!(minimizedStack.getObject() instanceof org.eclipse.e4.ui.workbench.addons.minmax.TrimStack)) |
| return; |
| |
| org.eclipse.e4.ui.workbench.addons.minmax.TrimStack ts = (org.eclipse.e4.ui.workbench.addons.minmax.TrimStack) minimizedStack |
| .getObject(); |
| if (!(ts.getMinimizedElement() instanceof MPartStack)) |
| return; |
| |
| MPartStack stack = (MPartStack) ts.getMinimizedElement(); |
| MUIElement stackSel = stack.getSelectedElement(); |
| MPart thePart = null; |
| if (stackSel instanceof MPart) { |
| thePart = (MPart) stackSel; |
| } else if (stackSel instanceof MPlaceholder) { |
| MPlaceholder ph = (MPlaceholder) stackSel; |
| if (ph.getRef() instanceof MPart) { |
| thePart = (MPart) ph.getRef(); |
| } |
| } |
| |
| if (thePart == null) |
| return; |
| |
| if (UIEvents.isADD(event)) { |
| if (UIEvents.contains(event, UIEvents.EventTags.NEW_VALUE, |
| org.eclipse.e4.ui.workbench.addons.minmax.TrimStack.MINIMIZED_AND_SHOWING)) { |
| firePartVisible(thePart); |
| } |
| } else if (UIEvents.isREMOVE(event)) { |
| if (UIEvents.contains(event, UIEvents.EventTags.OLD_VALUE, |
| org.eclipse.e4.ui.workbench.addons.minmax.TrimStack.MINIMIZED_AND_SHOWING)) { |
| firePartHidden(thePart); |
| } |
| } |
| } |
| |
| /** |
| * Boolean field to determine whether DND support has been added to the |
| * shared area yet. |
| * |
| * @see #installAreaDropSupport(Control) |
| */ |
| private boolean dndSupportInstalled = false; |
| |
| /** |
| * Constructs a page. <code>restoreState(IMemento)</code> should be |
| * called to restore this page from data stored in a persistance file. |
| * |
| * @param w |
| * the parent window |
| * @param input |
| * the page input |
| * @throws WorkbenchException |
| */ |
| public WorkbenchPage(WorkbenchWindow w, IAdaptable input) |
| throws WorkbenchException { |
| super(); |
| init(w, null, input, false); |
| } |
| |
| /** |
| * Allow access to the UI model that this page is managing |
| * @return the MWindow element for this page |
| */ |
| public MWindow getWindowModel() { |
| return window; |
| |
| } |
| /** |
| * Activates a part. The part will be brought to the front and given focus. |
| * |
| * @param part |
| * the part to activate |
| */ |
| @Override |
| public void activate(IWorkbenchPart part) { |
| if (part == null || !certifyPart(part) || legacyWindow.isClosing()) { |
| return; |
| } |
| MPart mpart = findPart(part); |
| if (mpart != null) { |
| partService.activate(mpart); |
| actionSwitcher.updateActivePart(part); |
| } |
| } |
| |
| /** |
| * Adds an IPartListener to the part service. |
| */ |
| @Override |
| public void addPartListener(IPartListener l) { |
| partListenerList.add(l); |
| } |
| |
| /** |
| * Adds an IPartListener to the part service. |
| */ |
| @Override |
| public void addPartListener(IPartListener2 l) { |
| partListener2List.add(l); |
| } |
| |
| /** |
| * Implements IWorkbenchPage |
| * |
| * @see org.eclipse.ui.IWorkbenchPage#addPropertyChangeListener(IPropertyChangeListener) |
| * @since 2.0 |
| * @deprecated individual views should store a working set if needed and |
| * register a property change listener directly with the |
| * working set manager to receive notification when the view |
| * working set is removed. |
| */ |
| @Deprecated |
| @Override |
| public void addPropertyChangeListener(IPropertyChangeListener listener) { |
| propertyChangeListeners.add(listener); |
| } |
| |
| @Override |
| public void addSelectionListener(ISelectionListener listener) { |
| selectionService.addSelectionListener(listener); |
| } |
| |
| @Override |
| public void addSelectionListener(String partId, ISelectionListener listener) { |
| selectionService.addSelectionListener(partId, listener); |
| } |
| |
| @Override |
| public void addPostSelectionListener(ISelectionListener listener) { |
| selectionService.addPostSelectionListener(listener); |
| } |
| |
| @Override |
| public void addPostSelectionListener(String partId, |
| ISelectionListener listener) { |
| selectionService.addPostSelectionListener(partId, listener); |
| } |
| |
| /** |
| * Moves a part forward in the Z order of a perspective so it is visible. |
| * If the part is in the same stack as the active part, the new part is |
| * activated. |
| * |
| * @param part |
| * the part to bring to move forward |
| */ |
| @Override |
| public void bringToTop(IWorkbenchPart part) { |
| // Sanity check. |
| MPart mpart = findPart(part); |
| if (mpart != null) { |
| partService.bringToTop(mpart); |
| } |
| } |
| |
| public MPart findPart(IWorkbenchPart part) { |
| if (part == null) { |
| return null; |
| } |
| |
| for (IViewReference reference : viewReferences) { |
| if (part == reference.getPart(false)) { |
| return ((WorkbenchPartReference) reference).getModel(); |
| } |
| } |
| |
| for (IEditorReference reference : editorReferences) { |
| if (part == reference.getPart(false)) { |
| return ((WorkbenchPartReference) reference).getModel(); |
| } |
| } |
| return null; |
| } |
| |
| public EditorReference createEditorReferenceForPart(final MPart part, IEditorInput input, |
| String editorId, |
| IMemento memento) { |
| IEditorRegistry registry = legacyWindow.getWorkbench().getEditorRegistry(); |
| EditorDescriptor descriptor = (EditorDescriptor) registry.findEditor(editorId); |
| final EditorReference ref = new EditorReference(window.getContext(), this, part, input, |
| descriptor, memento); |
| addEditorReference(ref); |
| ref.subscribe(); |
| return ref; |
| } |
| |
| private List<EditorReference> getOrderedEditorReferences() { |
| |
| List<EditorReference> editorRefs = new ArrayList<>(); |
| List<MPart> visibleEditors = modelService.findElements(window, |
| CompatibilityEditor.MODEL_ELEMENT_ID, MPart.class, null); |
| for (MPart editor : visibleEditors) { |
| if (editor.isToBeRendered()) { |
| EditorReference ref = getEditorReference(editor); |
| if (ref != null && !editorRefs.contains(ref)) { |
| editorRefs.add(ref); |
| } |
| } |
| } |
| |
| return editorRefs; |
| } |
| |
| List<EditorReference> getSortedEditorReferences() { |
| return getSortedEditorReferences(false); |
| } |
| |
| private List<EditorReference> getSortedEditorReferences(boolean allPerspectives) { |
| List<EditorReference> sortedReferences = new ArrayList<>(); |
| for (MPart part : activationList) { |
| for (EditorReference ref : editorReferences) { |
| if (ref.getModel() == part) { |
| sortedReferences.add(ref); |
| break; |
| } |
| } |
| } |
| |
| for (EditorReference ref : editorReferences) { |
| if (!sortedReferences.contains(ref)) { |
| sortedReferences.add(ref); |
| } |
| } |
| |
| MPerspective currentPerspective = getCurrentPerspective(); |
| if (currentPerspective != null) { |
| int scope = allPerspectives ? WINDOW_SCOPE : EModelService.PRESENTATION; |
| List<MPart> placeholders = modelService.findElements(window, |
| CompatibilityEditor.MODEL_ELEMENT_ID, MPart.class, null, scope); |
| List<EditorReference> visibleReferences = new ArrayList<>(); |
| for (EditorReference reference : sortedReferences) { |
| for (MPart placeholder : placeholders) { |
| if (reference.getModel() == placeholder && placeholder.isToBeRendered()) { |
| // only rendered placeholders are valid references |
| visibleReferences.add(reference); |
| } |
| } |
| } |
| |
| return visibleReferences; |
| } |
| |
| return sortedReferences; |
| } |
| |
| public List<EditorReference> getInternalEditorReferences() { |
| return editorReferences; |
| } |
| |
| public EditorReference getEditorReference(MPart part) { |
| for (EditorReference ref : editorReferences) { |
| if (ref.getModel() == part) { |
| return ref; |
| } |
| } |
| return null; |
| } |
| |
| public ViewReference getViewReference(MPart part) { |
| for (ViewReference ref : viewReferences) { |
| if (ref.getModel() == part) { |
| return ref; |
| } |
| } |
| return null; |
| } |
| |
| private boolean contains(ViewReference reference) { |
| for (ViewReference viewReference : viewReferences) { |
| if (reference.getModel().getElementId().equals(viewReference.getModel().getElementId())) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public void addViewReference(ViewReference reference) { |
| if (!contains(reference)) { |
| viewReferences.add(reference); |
| } |
| } |
| |
| public void addEditorReference(EditorReference editorReference) { |
| WorkbenchPage curPage = (WorkbenchPage) editorReference.getPage(); |
| |
| // Ensure that the page is up-to-date |
| if (curPage != this) { |
| curPage.editorReferences.remove(editorReference); |
| editorReference.setPage(this); |
| } |
| |
| // Avoid dups |
| if (!editorReferences.contains(editorReference)) { |
| editorReferences.add(editorReference); |
| } |
| } |
| |
| MPartDescriptor findDescriptor(String id) { |
| return modelService.getPartDescriptor(id); |
| } |
| |
| /** |
| * Searches the workbench window for a part with the given view id and |
| * secondary id (if desired) given the specified search rules. |
| * |
| * @param viewId |
| * the id of the view |
| * @param secondaryId |
| * the secondary id of the view, or <code>null</code> if the view |
| * to search for should be one without a secondary id defined |
| * @param searchFlags |
| * the desired search locations |
| * @return the part with the specified view id and secondary id, or |
| * <code>null</code> if it could not be found in this page's parent |
| * workbench window |
| * @see EModelService#findElements(MUIElement, String, Class, List, int) |
| */ |
| private MPart findPart(String viewId, int searchFlags) { |
| List<MPart> parts = modelService.findElements(getWindowModel(), viewId, MPart.class, null, |
| searchFlags); |
| if (parts.size() > 0) |
| return parts.get(0); |
| |
| return null; |
| } |
| |
| PartState convert(int mode) { |
| switch (mode) { |
| case VIEW_ACTIVATE: |
| return PartState.ACTIVATE; |
| case VIEW_VISIBLE: |
| return PartState.VISIBLE; |
| case VIEW_CREATE: |
| return PartState.CREATE; |
| } |
| throw new IllegalArgumentException(WorkbenchMessages.WorkbenchPage_IllegalViewMode); |
| } |
| |
| /** |
| * Shows a view. |
| * |
| * Assumes that a busy cursor is active. |
| */ |
| protected IViewPart busyShowView(String viewId, int mode) throws PartInitException { |
| switch (mode) { |
| case VIEW_ACTIVATE: |
| case VIEW_VISIBLE: |
| case VIEW_CREATE: |
| break; |
| default: |
| throw new IllegalArgumentException(WorkbenchMessages.WorkbenchPage_IllegalViewMode); |
| } |
| |
| MPart part = findPart(viewId, EModelService.ANYWHERE); |
| if (part == null) { |
| MPlaceholder ph = partService.createSharedPart(viewId, false); |
| if (ph == null) { |
| throw new PartInitException(NLS.bind(WorkbenchMessages.ViewFactory_couldNotCreate, |
| viewId)); |
| } |
| |
| part = (MPart) ph.getRef(); |
| part.setCurSharedRef(ph); |
| } |
| |
| part = showPart(mode, part); |
| |
| ViewReference ref = getViewReference(part); |
| |
| return (IViewPart) ref.getPart(true); |
| } |
| private MPart showPart(int mode, MPart part) { |
| switch (mode) { |
| case VIEW_ACTIVATE: |
| partService.showPart(part, PartState.ACTIVATE); |
| if (part.getObject() instanceof CompatibilityView) { |
| CompatibilityView compatibilityView = (CompatibilityView) part.getObject(); |
| actionSwitcher.updateActivePart(compatibilityView.getPart()); |
| } |
| break; |
| case VIEW_VISIBLE: |
| MPart activePart = partService.getActivePart(); |
| if (activePart == null) { |
| partService.showPart(part, PartState.ACTIVATE); |
| if (part.getObject() instanceof CompatibilityView) { |
| CompatibilityView compatibilityView = (CompatibilityView) part.getObject(); |
| actionSwitcher.updateActivePart(compatibilityView.getPart()); |
| } |
| } else { |
| part = ((PartServiceImpl) partService).addPart(part); |
| MPlaceholder activePlaceholder = activePart.getCurSharedRef(); |
| MUIElement activePartParent = activePlaceholder == null ? activePart |
| .getParent() : activePlaceholder.getParent(); |
| partService.showPart(part, PartState.CREATE); |
| if (part.getCurSharedRef() == null || part.getCurSharedRef().getParent() != activePartParent) { |
| partService.bringToTop(part); |
| } |
| } |
| break; |
| case VIEW_CREATE: |
| partService.showPart(part, PartState.CREATE); |
| |
| // Report the visibility of the created part |
| MStackElement sElement = part; |
| if (part.getCurSharedRef() != null) |
| sElement = part.getCurSharedRef(); |
| MUIElement parentElement = sElement.getParent(); |
| if (parentElement instanceof MPartStack) { |
| MPartStack partStack = (MPartStack) parentElement; |
| if (partStack.getSelectedElement() == sElement |
| && !partStack.getTags().contains(IPresentationEngine.MINIMIZED)) { |
| firePartVisible(part); |
| } else { |
| firePartHidden(part); |
| } |
| } else { |
| firePartVisible(part); // Stand-alone part |
| } |
| break; |
| } |
| return part; |
| } |
| |
| /** |
| * Returns whether a part exists in the current page. |
| */ |
| private boolean certifyPart(IWorkbenchPart part) { |
| //Workaround for bug 22325 |
| if (part != null && !(part.getSite() instanceof PartSite)) { |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Closes this page. |
| */ |
| @Override |
| public boolean close() { |
| final boolean[] ret = new boolean[1]; |
| BusyIndicator.showWhile(null, new Runnable() { |
| @Override |
| public void run() { |
| ret[0] = close(true, true); |
| } |
| }); |
| return ret[0]; |
| } |
| |
| public boolean closeAllSavedEditors() { |
| // get the Saved editors |
| IEditorReference editors[] = getEditorReferences(); |
| IEditorReference savedEditors[] = new IEditorReference[editors.length]; |
| int j = 0; |
| for (IEditorReference editor : editors) { |
| if (!editor.isDirty()) { |
| savedEditors[j++] = editor; |
| } |
| } |
| //there are no unsaved editors |
| if (j == 0) { |
| return true; |
| } |
| IEditorReference[] newSaved = new IEditorReference[j]; |
| System.arraycopy(savedEditors, 0, newSaved, 0, j); |
| return closeEditors(newSaved, false); |
| } |
| |
| /** |
| * See IWorkbenchPage |
| */ |
| @Override |
| public boolean closeAllEditors(boolean save) { |
| return closeEditors(getEditorReferences(), save); |
| } |
| |
| /** |
| * See IWorkbenchPage |
| */ |
| @Override |
| public boolean closeEditors(IEditorReference[] refArray, boolean save) { |
| if (refArray.length == 0) { |
| return true; |
| } |
| |
| // Check if we're being asked to close any parts that are already closed |
| // or cannot |
| // be closed at this time |
| ArrayList<IEditorReference> editorRefs = new ArrayList<>(); |
| for (IEditorReference reference : refArray) { |
| // If we're in the middle of creating this part, this is a |
| // programming error. Abort the entire |
| // close operation. This usually occurs if someone tries to open a |
| // dialog in a method that |
| // isn't allowed to do so, and a *syncExec tries to close the part. |
| // If this shows up in a log |
| // file with a dialog's event loop on the stack, then the code that |
| // opened the dialog is usually |
| // at fault. |
| if (reference == partBeingActivated) { |
| WorkbenchPlugin.log(new RuntimeException( |
| "WARNING: Blocked recursive attempt to close part " //$NON-NLS-1$ |
| + partBeingActivated.getId() |
| + " while still in the middle of activating it")); //$NON-NLS-1$ |
| return false; |
| } |
| |
| if (reference instanceof WorkbenchPartReference) { |
| WorkbenchPartReference ref = (WorkbenchPartReference) reference; |
| |
| // If we're being asked to close a part that is disposed (ie: |
| // already closed), |
| // skip it and proceed with closing the remaining parts. |
| if (ref.isDisposed()) { |
| continue; |
| } |
| } |
| |
| editorRefs.add(reference); |
| } |
| |
| // if active navigation position belongs to an editor being closed, |
| // update it |
| // (The navigation position for an editor N was updated as an editor N + |
| // 1 |
| // was activated. As a result, all but the last editor have up-to-date |
| // navigation positions.) |
| for (IEditorReference ref : editorRefs) { |
| IEditorPart oldPart = ref.getEditor(false); |
| if (oldPart == null) |
| continue; |
| if (navigationHistory.updateActive(oldPart)) |
| break; // updated - skip the rest |
| } |
| |
| // notify the model manager before the close |
| List<IWorkbenchPart> partsToClose = new ArrayList<>(); |
| for (IEditorReference ref : editorRefs) { |
| IEditorPart refPart = ref.getEditor(false); |
| if (refPart != null) { |
| partsToClose.add(refPart); |
| } |
| } |
| |
| boolean confirm = true; |
| SaveablesList modelManager = null; |
| Object postCloseInfo = null; |
| if (partsToClose.size() > 0) { |
| modelManager = (SaveablesList) getWorkbenchWindow().getService( |
| ISaveablesLifecycleListener.class); |
| // this may prompt for saving and return null if the user canceled: |
| postCloseInfo = modelManager.preCloseParts(partsToClose, save, getWorkbenchWindow()); |
| if (postCloseInfo == null) { |
| return false; |
| } |
| confirm = false; |
| } |
| |
| // Fire pre-removal changes |
| for (IEditorReference ref : editorRefs) { |
| // Notify interested listeners before the close |
| legacyWindow.firePerspectiveChanged(this, getPerspective(), ref, CHANGE_EDITOR_CLOSE); |
| |
| } |
| |
| deferUpdates(true); |
| try { |
| if (modelManager != null) { |
| modelManager.postClose(postCloseInfo); |
| } |
| |
| // Close all editors. |
| for (Iterator<IEditorReference> it = editorRefs.iterator(); it.hasNext();) { |
| IEditorReference ref = it.next(); |
| // hide editors that haven't been instantiated first |
| if (ref.getPart(false) == null) { |
| if (!(hidePart(((EditorReference) ref).getModel(), false, confirm, false, false))) { |
| return false; |
| } |
| // hidden successfully, remove it from the list |
| it.remove(); |
| } |
| } |
| |
| MPart activePart = findPart(getActiveEditor()); |
| boolean closeActivePart = false; |
| // now hide all instantiated editors |
| for (IEditorReference editorRef : editorRefs) { |
| MPart model = ((EditorReference) editorRef).getModel(); |
| if (activePart == model) { |
| closeActivePart = true; |
| } else if (!(hidePart(model, false, confirm, false, false))) { |
| // saving should've been handled earlier above |
| return false; |
| } |
| } |
| |
| // close the active part last to minimize activation churn |
| if (closeActivePart) { |
| if (!(hidePart(activePart, false, confirm, false))) { |
| return false; |
| } |
| } |
| } finally { |
| deferUpdates(false); |
| } |
| |
| // Notify interested listeners after the close |
| legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_EDITOR_CLOSE); |
| |
| // Return true on success. |
| return true; |
| } |
| |
| public boolean closeEditor(IEditorReference editor) { |
| if (getInternalEditorReferences().contains(editor)) { |
| MPart part = ((EditorReference) editor).getModel(); |
| hidePart(part, false, false, false, false); |
| |
| MElementContainer<MUIElement> parent = part.getParent(); |
| if (parent != null) { |
| parent.getChildren().remove(part); |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| private boolean hidePart(MPart part, boolean save, boolean confirm, boolean force) { |
| return hidePart(part, save, confirm, force, true); |
| } |
| |
| private boolean hidePart(MPart part, boolean save, boolean confirm, boolean force, boolean local) { |
| if (!partService.getParts().contains(part)) { |
| if (local) { |
| return false; |
| } |
| part.setToBeRendered(false); |
| return true; |
| } |
| |
| Object clientObject = part.getObject(); |
| if (!(clientObject instanceof CompatibilityPart)) { |
| // either not a 3.x part or it's an e4 part, should still hide it |
| if (save) { |
| // save as necessary |
| if (partService.savePart(part, confirm)) { |
| partService.hidePart(part, force); |
| return true; |
| } |
| return false; |
| } |
| partService.hidePart(part, force); |
| return true; |
| } |
| |
| CompatibilityPart compatibilityPart = (CompatibilityPart) clientObject; |
| IWorkbenchPart workbenchPart = compatibilityPart.getPart(); |
| if (save) { |
| ISaveablePart saveablePart = SaveableHelper.getSaveable(workbenchPart); |
| if (saveablePart != null) { |
| if (saveablePart.isSaveOnCloseNeeded()) { |
| if (!saveSaveable(saveablePart, workbenchPart, confirm, true)) { |
| return false; |
| } |
| } |
| } |
| } |
| |
| for (IViewReference viewRef : viewReferences) { |
| if (workbenchPart == viewRef.getPart(false)) { |
| partService.hidePart(part, force); |
| return true; |
| } |
| } |
| |
| for (IEditorReference viewRef : editorReferences) { |
| if (workbenchPart == viewRef.getPart(false)) { |
| partService.hidePart(part, force); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Enables or disables listener notifications. This is used to delay listener notifications until the |
| * end of a public method. |
| * |
| * @param shouldDefer |
| */ |
| private void deferUpdates(boolean shouldDefer) { |
| if (shouldDefer) { |
| if (deferCount == 0) { |
| startDeferring(); |
| } |
| deferCount++; |
| } else { |
| deferCount--; |
| if (deferCount == 0) { |
| handleDeferredEvents(); |
| } |
| } |
| } |
| |
| private void startDeferring() { |
| // TODO compat: do we defer events |
| } |
| |
| private void handleDeferredEvents() { |
| // TODO compat: do we handler defered events |
| } |
| |
| public boolean closeEditor(IEditorReference editorRef, boolean save) { |
| return closeEditors(new IEditorReference[] {editorRef}, save); |
| } |
| |
| /** |
| * See IWorkbenchPage#closeEditor |
| */ |
| @Override |
| public boolean closeEditor(IEditorPart editor, boolean save) { |
| IWorkbenchPartReference ref = getReference(editor); |
| if (ref instanceof IEditorReference) { |
| return closeEditors(new IEditorReference[] {(IEditorReference) ref}, save); |
| } |
| return false; |
| } |
| |
| /** |
| * Closes the specified perspective. |
| * |
| * @param desc |
| * the perspective to close |
| * @param perspectiveId |
| * the id of the perspective being closed |
| * @param saveParts |
| * <code>true</code> if dirty parts should be prompted for its |
| * contents to be saved, <code>false</code> otherwise |
| */ |
| private void closePerspective(IPerspectiveDescriptor desc, String perspectiveId, |
| boolean saveParts) { |
| MPerspective persp = (MPerspective) modelService.find(perspectiveId, window); |
| // check to ensure this perspective actually exists in this window |
| if (persp != null) { |
| if (saveParts) { |
| List<IWorkbenchPart> partsToSave = new ArrayList<>(); |
| // retrieve all parts under the specified perspective |
| List<MPart> parts = modelService.findElements(persp, null, MPart.class, null); |
| if (!parts.isEmpty()) { |
| // filter out any parts that are visible in any other |
| // perspectives |
| for (MPerspective perspective : getPerspectiveStack().getChildren()) { |
| if (perspective != persp) { |
| parts.removeAll(modelService.findElements(perspective, null, |
| MPart.class, null)); |
| } |
| } |
| |
| if (!parts.isEmpty()) { |
| for (Iterator<MPart> it = parts.iterator(); it.hasNext();) { |
| MPart part = it.next(); |
| if (part.isDirty()) { |
| Object object = part.getObject(); |
| if (object instanceof CompatibilityPart) { |
| IWorkbenchPart workbenchPart = ((CompatibilityPart) object) |
| .getPart(); |
| ISaveablePart saveablePart = SaveableHelper.getSaveable(workbenchPart); |
| if (saveablePart != null) { |
| if (!saveablePart.isSaveOnCloseNeeded()) { |
| part.setDirty(false); |
| it.remove(); |
| } else { |
| partsToSave.add(workbenchPart); |
| } |
| } |
| } |
| } else { |
| it.remove(); |
| } |
| } |
| |
| if (!partsToSave.isEmpty()) { |
| if (!saveAll(partsToSave, true, true, false, legacyWindow, legacyWindow)) { |
| // user cancel |
| return; |
| } |
| } |
| } |
| } |
| } |
| |
| // Remove from caches |
| sortedPerspectives.remove(desc); |
| // check if we're closing the currently active perspective |
| if (getPerspectiveStack().getSelectedElement() == persp |
| && !sortedPerspectives.isEmpty()) { |
| // get the perspective that was last active and set it |
| IPerspectiveDescriptor lastActive = sortedPerspectives.get(sortedPerspectives |
| .size() - 1); |
| if (lastActive != null) { |
| setPerspective(lastActive); |
| } |
| } |
| modelService.removePerspectiveModel(persp, window); |
| modelToPerspectiveMapping.remove(persp); |
| |
| legacyWindow.firePerspectiveClosed(this, desc); |
| } |
| } |
| |
| @Override |
| public void closePerspective(IPerspectiveDescriptor desc, boolean saveParts, boolean closePage) { |
| closePerspective(desc, desc.getId(), saveParts, closePage); |
| } |
| |
| public void closePerspective(IPerspectiveDescriptor desc, String perspectiveId, |
| boolean saveParts, boolean closePage) { |
| MPerspective persp = (MPerspective) modelService.find(perspectiveId, window); |
| // check to ensure this perspective actually exists in this window |
| if (persp != null) { |
| persp.getTags().add("PerspClosing"); //$NON-NLS-1$ |
| try { |
| MPerspectiveStack perspectiveStack = modelService.findElements(window, null, |
| MPerspectiveStack.class, null).get(0); |
| if (perspectiveStack.getChildren().size() == 1) { |
| closeAllPerspectives(saveParts, closePage); |
| } else { |
| closePerspective(desc, perspectiveId, saveParts); |
| } |
| } finally { |
| persp.getTags().remove("PerspClosing"); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| @Override |
| public void closeAllPerspectives(boolean saveEditors, boolean closePage) { |
| boolean okToProceed = closeAllEditors(true); |
| if (okToProceed) { |
| List<MPerspective> kids = new ArrayList<>(_perspectiveStack.getChildren()); |
| MPerspective curPersp = _perspectiveStack.getSelectedElement(); |
| for (MPerspective persp : kids) { |
| if (persp != curPersp) { |
| closePerspective(getPerspectiveDesc(persp.getElementId()), |
| persp.getElementId(), false); |
| } |
| } |
| if (curPersp != null) { |
| closePerspective(getPerspectiveDesc(curPersp.getElementId()), |
| curPersp.getElementId(), |
| false); |
| } |
| if (closePage) { |
| close(); |
| } |
| } |
| } |
| |
| private boolean close(boolean save, boolean unsetPage) { |
| if (save && !saveAllEditors(true, true, true)) { |
| return false; |
| } |
| |
| Collection<MPart> partsToHide = partService.getParts(); |
| // workaround for bug 455281 |
| List<MPart> partsOutsidePersp = modelService.findElements(window, null, MPart.class, null, |
| EModelService.OUTSIDE_PERSPECTIVE); |
| partsToHide.removeAll(partsOutsidePersp); |
| |
| for (MPart part : partsToHide) { |
| // no save, no confirm, force |
| hidePart(part, false, true, true); |
| } |
| |
| MPerspectiveStack perspectiveStack = modelService.findElements(window, null, |
| MPerspectiveStack.class, null).get(0); |
| MPerspective current = perspectiveStack.getSelectedElement(); |
| for (Object perspective : perspectiveStack.getChildren().toArray()) { |
| if (perspective != current) { |
| modelService.removePerspectiveModel((MPerspective) perspective, window); |
| } |
| } |
| |
| if (current != null) { |
| modelService.removePerspectiveModel(current, window); |
| } |
| |
| viewReferences.clear(); |
| editorReferences.clear(); |
| sortedPerspectives.clear(); |
| modelToPerspectiveMapping.clear(); |
| |
| if (unsetPage) { |
| legacyWindow.setActivePage(null); |
| partService.removePartListener(e4PartListener); |
| broker.unsubscribe(selectionHandler); |
| broker.unsubscribe(widgetHandler); |
| broker.unsubscribe(referenceRemovalEventHandler); |
| broker.unsubscribe(firingHandler); |
| broker.unsubscribe(childrenHandler); |
| partEvents.clear(); |
| |
| partListenerList.clear(); |
| partListener2List.clear(); |
| propertyChangeListeners.clear(); |
| |
| selectionService.dispose(); |
| |
| ContextInjectionFactory.uninject(this, window.getContext()); |
| } |
| return true; |
| } |
| |
| /** |
| * Forces all perspectives on the page to zoom out. |
| */ |
| public void unzoomAllPerspectives() { |
| // TODO compat: we have no min/max behaviour |
| } |
| |
| |
| |
| /** |
| * Cleanup. |
| */ |
| public void dispose() { |
| |
| // // Always unzoom |
| // if (isZoomed()) { |
| // zoomOut(); |
| // } |
| // |
| // // makeActiveEditor(null); |
| // // makeActive(null); |
| // |
| // // Close and dispose the editors. |
| // closeAllEditors(false); |
| // |
| // // Need to make sure model data is cleaned up when the page is |
| // // disposed. Collect all the views on the page and notify the |
| // // saveable list of a pre/post close. This will free model data. |
| // IWorkbenchPartReference[] partsToClose = getOpenParts(); |
| // List dirtyParts = new ArrayList(partsToClose.length); |
| // for (int i = 0; i < partsToClose.length; i++) { |
| // IWorkbenchPart part = partsToClose[i].getPart(false); |
| // if (part != null && part instanceof IViewPart) { |
| // dirtyParts.add(part); |
| // } |
| // } |
| // SaveablesList saveablesList = (SaveablesList) |
| // getWorkbenchWindow().getWorkbench().getService(ISaveablesLifecycleListener.class); |
| // Object postCloseInfo = saveablesList.preCloseParts(dirtyParts, |
| // false,getWorkbenchWindow()); |
| // saveablesList.postClose(postCloseInfo); |
| // |
| // // Get rid of perspectives. This will close the views. |
| // Iterator itr = perspList.iterator(); |
| // while (itr.hasNext()) { |
| // Perspective perspective = (Perspective) itr.next(); |
| // legacyWindow.firePerspectiveClosed(this, perspective.getDesc()); |
| // perspective.dispose(); |
| // } |
| // perspList = new PerspectiveList(); |
| // |
| // // Capture views. |
| // IViewReference refs[] = viewFactory.getViews(); |
| // |
| // if (refs.length > 0) { |
| // // Dispose views. |
| // for (int i = 0; i < refs.length; i++) { |
| // final WorkbenchPartReference ref = (WorkbenchPartReference) refs[i]; |
| // //partList.removePart(ref); |
| // //firePartClosed(refs[i]); |
| // SafeRunner.run(new SafeRunnable() { |
| // public void run() { |
| // // WorkbenchPlugin.log(new Status(IStatus.WARNING, |
| // WorkbenchPlugin.PI_WORKBENCH, |
| //// Status.OK, "WorkbenchPage leaked a refcount for view " + ref.getId(), null)); //$NON-NLS-1$//$NON-NLS-2$ |
| // |
| // ref.dispose(); |
| // } |
| // |
| // public void handleException(Throwable e) { |
| // } |
| // }); |
| // } |
| // } |
| // |
| // activationList = new ActivationList(); |
| // |
| // // Get rid of editor presentation. |
| // editorPresentation.dispose(); |
| // |
| // // Get rid of composite. |
| // composite.dispose(); |
| // |
| // navigationHistory.dispose(); |
| // |
| // stickyViewMan.clear(); |
| // |
| // if (tracker != null) { |
| // tracker.close(); |
| // } |
| // |
| // // if we're destroying a window in a non-shutdown situation then we |
| // should |
| // // clean up the working set we made. |
| // if (!legacyWindow.getWorkbench().isClosing()) { |
| // if (aggregateWorkingSet != null) { |
| // PlatformUI.getWorkbench().getWorkingSetManager().removeWorkingSet(aggregateWorkingSet); |
| // } |
| // } |
| } |
| |
| |
| |
| /** |
| * @return NavigationHistory |
| */ |
| @Override |
| public INavigationHistory getNavigationHistory() { |
| return navigationHistory; |
| } |
| |
| public boolean editActionSets() { |
| Perspective persp = getActivePerspective(); |
| if (persp == null) { |
| return false; |
| } |
| |
| // Create list dialog. |
| CustomizePerspectiveDialog dlg = legacyWindow.createCustomizePerspectiveDialog(persp, |
| window.getContext()); |
| // Open. |
| boolean ret = (dlg.open() == Window.OK); |
| if (ret) { |
| legacyWindow.updateActionSets(); |
| legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_RESET); |
| legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_RESET_COMPLETE); |
| } |
| return ret; |
| } |
| |
| |
| /** |
| * See IWorkbenchPage@findView. |
| */ |
| @Override |
| public IViewPart findView(String id) { |
| IViewReference ref = findViewReference(id); |
| if (ref == null) { |
| return null; |
| } |
| return ref.getView(true); |
| } |
| |
| @Override |
| public IViewReference findViewReference(String viewId) { |
| for (IViewReference reference : getViewReferences()) { |
| ViewReference ref = (ViewReference) reference; |
| if (viewId.equals(ref.getModel().getElementId())) { |
| return reference; |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public IViewReference findViewReference(String viewId, String secondaryId) { |
| String compoundId = viewId; |
| if (secondaryId != null && secondaryId.length() > 0) |
| compoundId += ":" + secondaryId; //$NON-NLS-1$ |
| return findViewReference(compoundId); |
| } |
| |
| public void createViewReferenceForPart(final MPart part, String viewId) { |
| // If the id contains a ':' use the part before it as the descriptor id |
| int colonIndex = viewId.indexOf(':'); |
| String descId = colonIndex == -1 ? viewId : viewId.substring(0, colonIndex); |
| |
| IViewDescriptor desc = getWorkbenchWindow().getWorkbench().getViewRegistry().find(descId); |
| final ViewReference ref = new ViewReference(window.getContext(), this, part, |
| (ViewDescriptor) desc); |
| if (contains(ref)) { |
| return; |
| } |
| |
| IEclipseContext partContext = part.getContext(); |
| if (partContext == null) { |
| ref.subscribe(); |
| } else { |
| partContext.set(ViewReference.class.getName(), ref); |
| } |
| addViewReference(ref); |
| } |
| |
| /** |
| * Notify property change listeners about a property change. |
| * |
| * @param changeId |
| * the change id |
| * @param oldValue |
| * old property value |
| * @param newValue |
| * new property value |
| */ |
| private void firePropertyChange(String changeId, Object oldValue, |
| Object newValue) { |
| |
| UIListenerLogging.logPagePropertyChanged(this, changeId, oldValue, newValue); |
| |
| PropertyChangeEvent event = new PropertyChangeEvent(this, changeId, |
| oldValue, newValue); |
| |
| for (IPropertyChangeListener listener : propertyChangeListeners) { |
| listener.propertyChange(event); |
| } |
| } |
| |
| /* |
| * Returns the action bars. |
| */ |
| public IActionBars getActionBars() { |
| if (actionBars == null) { |
| actionBars = new WWinActionBars(legacyWindow); |
| } |
| return actionBars; |
| } |
| |
| /** |
| * Returns an array of the visible action sets. |
| * |
| * @return an array of the currently visible action sets |
| */ |
| public IActionSetDescriptor[] getActionSets() { |
| Collection<?> collection = actionSets.getVisibleItems(); |
| return collection.toArray(new IActionSetDescriptor[collection.size()]); |
| } |
| |
| /** |
| * @see IWorkbenchPage |
| */ |
| @Override |
| public IEditorPart getActiveEditor() { |
| IWorkbenchPart activePart = getActivePart(); |
| if (activePart instanceof IEditorPart) { |
| // if the currently active part is an editor, return it |
| return (IEditorPart) activePart; |
| } |
| |
| if (!activationList.isEmpty()) { |
| IEditorPart editor = findActiveEditor(); |
| if (editor != null) { |
| return editor; |
| } |
| } |
| |
| MUIElement area = findSharedArea(); |
| if (area instanceof MPlaceholder) { |
| area = ((MPlaceholder) area).getRef(); |
| } |
| if (area != null && area.isVisible() && area.isToBeRendered()) { |
| // we have a shared area, try iterating over its editors first |
| List<MPart> editors = modelService.findElements(area, |
| CompatibilityEditor.MODEL_ELEMENT_ID, MPart.class, null); |
| for (MPart model : editors) { |
| Object object = model.getObject(); |
| if (object instanceof CompatibilityEditor) { |
| CompatibilityEditor editor = (CompatibilityEditor) object; |
| // see bug 308492 |
| if (!editor.isBeingDisposed() && isInArea(area, model)) { |
| return ((CompatibilityEditor) object).getEditor(); |
| } |
| } |
| } |
| } |
| |
| MPerspective perspective = getPerspectiveStack().getSelectedElement(); |
| if (perspective == null) { |
| return null; |
| } |
| |
| List<MPart> parts = modelService.findElements(perspective, |
| CompatibilityEditor.MODEL_ELEMENT_ID, MPart.class, null); |
| for (MPart part : parts) { |
| Object object = part.getObject(); |
| if (object instanceof CompatibilityEditor) { |
| CompatibilityEditor editor = (CompatibilityEditor) object; |
| // see bug 308492 |
| if (!editor.isBeingDisposed()) { |
| if (isValid(perspective, part) || isValid(window, part)) { |
| return ((CompatibilityEditor) object).getEditor(); |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Searches and returns an editor from the activation list that is being |
| * displayed in the current presentation. If an editor is in the |
| * presentation but is behind another part it will not be returned. |
| * |
| * @return an editor that is being shown in the current presentation and was |
| * previously activated, editors that are behind another part in a |
| * stack will not be returned |
| */ |
| private IEditorPart findActiveEditor() { |
| List<MPart> candidates = new ArrayList<>(activationList); |
| MUIElement area = findSharedArea(); |
| if (area instanceof MPlaceholder) { |
| area = ((MPlaceholder) area).getRef(); |
| } |
| if (area != null && area.isVisible() && area.isToBeRendered()) { |
| // we have a shared area, try iterating over its editors first |
| List<MPart> editors = modelService |
| .findElements(area, CompatibilityEditor.MODEL_ELEMENT_ID, MPart.class, null); |
| for (Iterator<MPart> it = candidates.iterator(); it.hasNext();) { |
| MPart model = it.next(); |
| if (!editors.contains(model)) { |
| continue; |
| } |
| |
| Object object = model.getObject(); |
| if (object instanceof CompatibilityEditor) { |
| CompatibilityEditor editor = (CompatibilityEditor) object; |
| // see bug 308492 |
| if (!editor.isBeingDisposed() && isInArea(area, model)) { |
| return ((CompatibilityEditor) object).getEditor(); |
| } |
| } |
| it.remove(); |
| } |
| } |
| |
| MPerspective perspective = getPerspectiveStack().getSelectedElement(); |
| for (MPart model : activationList) { |
| Object object = model.getObject(); |
| if (object instanceof CompatibilityEditor) { |
| CompatibilityEditor editor = (CompatibilityEditor) object; |
| // see bug 308492 |
| if (!editor.isBeingDisposed()) { |
| if (isValid(perspective, model) || isValid(window, model)) { |
| return ((CompatibilityEditor) object).getEditor(); |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| private boolean isInArea(MUIElement area, MUIElement element) { |
| if (!element.isToBeRendered() || !element.isVisible()) { |
| return false; |
| } |
| |
| if (element == area) { |
| return true; |
| } |
| |
| MElementContainer<?> parent = element.getParent(); |
| if (parent == null || parent instanceof MPerspective || parent instanceof MWindow) { |
| return false; |
| } else if (parent instanceof MGenericStack) { |
| return parent.getSelectedElement() == element ? isValid(area, parent) : false; |
| } |
| |
| return isValid(area, parent); |
| } |
| |
| private boolean isValid(MUIElement ancestor, MUIElement element) { |
| if (!element.isToBeRendered() || !element.isVisible()) { |
| return false; |
| } |
| |
| if (element == ancestor) { |
| return true; |
| } |
| |
| MElementContainer<?> parent = element.getParent(); |
| if (parent == null) { |
| // might be a detached window |
| if (element instanceof MWindow) { |
| parent = (MElementContainer<?>) ((EObject) element).eContainer(); |
| } |
| |
| if (parent == null) { |
| return false; |
| } |
| } |
| |
| if (parent instanceof MGenericStack) { |
| return parent.getSelectedElement() == element ? isValid(ancestor, parent) : false; |
| } |
| |
| return isValid(ancestor, parent); |
| } |
| |
| @Override |
| public IWorkbenchPart getActivePart() { |
| MPart part = partService.getActivePart(); |
| return getWorkbenchPart(part); |
| } |
| |
| @Override |
| public IWorkbenchPartReference getActivePartReference() { |
| IWorkbenchPart part = getActivePart(); |
| return part == null ? null : getReference(part); |
| } |
| |
| public Composite getClientComposite() { |
| return composite; |
| } |
| |
| @Override |
| public IEditorPart[] getDirtyEditors() { |
| List<IEditorPart> dirtyEditors = new ArrayList<>(); |
| for (IEditorReference editorRef : editorReferences) { |
| IEditorPart editor = editorRef.getEditor(false); |
| if (editor != null && editor.isDirty()) { |
| dirtyEditors.add(editor); |
| } |
| } |
| return dirtyEditors.toArray(new IEditorPart[dirtyEditors.size()]); |
| } |
| |
| @Override |
| public IEditorPart findEditor(IEditorInput input) { |
| IEditorReference[] references = findEditors(input, null, MATCH_INPUT); |
| return references.length == 0 ? null : references[0].getEditor(true); |
| } |
| |
| @Override |
| public IEditorReference[] findEditors(IEditorInput input, String editorId, int matchFlags) { |
| List<EditorReference> filteredReferences = getSortedEditorReferences(); |
| |
| switch (matchFlags) { |
| case MATCH_INPUT: |
| List<IEditorReference> editorRefs = new ArrayList<>(); |
| for (EditorReference editorRef : filteredReferences) { |
| checkEditor(input, editorRefs, editorRef); |
| } |
| return editorRefs.toArray(new IEditorReference[editorRefs.size()]); |
| case MATCH_ID: |
| editorRefs = new ArrayList<>(); |
| for (IEditorReference editorRef : filteredReferences) { |
| if (editorId.equals(editorRef.getId())) { |
| editorRefs.add(editorRef); |
| } |
| } |
| return editorRefs.toArray(new IEditorReference[editorRefs.size()]); |
| default: |
| if ((matchFlags & IWorkbenchPage.MATCH_ID) != 0 |
| && (matchFlags & IWorkbenchPage.MATCH_INPUT) != 0) { |
| editorRefs = new ArrayList<>(); |
| for (EditorReference editorRef : filteredReferences) { |
| if (editorRef.getId().equals(editorId)) { |
| checkEditor(input, editorRefs, editorRef); |
| } |
| } |
| return editorRefs.toArray(new IEditorReference[editorRefs.size()]); |
| } |
| return new IEditorReference[0]; |
| } |
| } |
| |
| private void checkEditor(IEditorInput input, List<IEditorReference> editorRefs, |
| EditorReference editorRef) { |
| EditorDescriptor descriptor = editorRef.getDescriptor(); |
| if (descriptor != null) { |
| IEditorMatchingStrategy strategy = descriptor.getEditorMatchingStrategy(); |
| if (strategy != null && strategy.matches(editorRef, input)) { |
| editorRefs.add(editorRef); |
| return; |
| } |
| } |
| |
| IEditorPart editor = editorRef.getEditor(false); |
| if (editor == null) { |
| try { |
| String name = input.getName(); |
| IPersistableElement persistable = input.getPersistable(); |
| if (name == null || persistable == null) { |
| return; |
| } |
| |
| String id = persistable.getFactoryId(); |
| if (id != null && id.equals(editorRef.getFactoryId()) |
| && name.equals(editorRef.getName()) |
| && input.equals(editorRef.getEditorInput())) { |
| editorRefs.add(editorRef); |
| } |
| } catch (PartInitException e) { |
| WorkbenchPlugin.log(e); |
| } |
| } else if (editor.getEditorInput().equals(input)) { |
| editorRefs.add(editorRef); |
| } |
| } |
| |
| @Override |
| public IEditorPart[] getEditors() { |
| final IEditorReference[] editorReferences = getEditorReferences(); |
| int length = editorReferences.length; |
| IEditorPart[] editors = new IEditorPart[length]; |
| for (int i = 0; i < length; i++) { |
| editors[i] = editorReferences[i].getEditor(true); |
| } |
| return editors; |
| } |
| |
| @Override |
| public IEditorReference[] getEditorReferences() { |
| List<EditorReference> references = getOrderedEditorReferences(); |
| return references.toArray(new IEditorReference[references.size()]); |
| } |
| |
| public IEditorReference[] getSortedEditors() { |
| IWorkbenchPartReference[] parts = getSortedParts(true, false, false); |
| IEditorReference[] editors = new IEditorReference[parts.length]; |
| System.arraycopy(parts, 0, editors, 0, parts.length); |
| return editors; |
| } |
| |
| public IWorkbenchPartReference[] getSortedParts() { |
| return getSortedParts(true, true, false); |
| } |
| |
| /** |
| * Returns a sorted array of references to editors and/or views from this |
| * page. |
| * |
| * @param editors |
| * include editors |
| * @param views |
| * include views |
| * @param allPerspectives |
| * if {@code false}, does not include parts from inactive |
| * perspectives |
| * @return a sorted array of references to editors and/or views |
| */ |
| private IWorkbenchPartReference[] getSortedParts(boolean editors, boolean views, |
| boolean allPerspectives) { |
| if (!editors && !views) { |
| return new IWorkbenchPartReference[0]; |
| } |
| |
| List<IWorkbenchPartReference> sortedReferences = new ArrayList<>(); |
| IViewReference[] viewReferences = getViewReferences(allPerspectives); |
| List<EditorReference> editorReferences = getSortedEditorReferences(allPerspectives); |
| |
| activationLoop: for (MPart part : activationList) { |
| if (views) { |
| for (IViewReference ref : viewReferences) { |
| if (((ViewReference) ref).getModel() == part) { |
| sortedReferences.add(ref); |
| continue activationLoop; |
| } |
| } |
| } |
| |
| if (editors) { |
| for (EditorReference ref : editorReferences) { |
| if (ref.getModel() == part) { |
| sortedReferences.add(ref); |
| break; |
| } |
| } |
| } |
| } |
| |
| if (views) { |
| for (IViewReference ref : viewReferences) { |
| if (!sortedReferences.contains(ref)) { |
| sortedReferences.add(ref); |
| } |
| } |
| } |
| |
| if (editors) { |
| for (EditorReference ref : editorReferences) { |
| if (!sortedReferences.contains(ref)) { |
| sortedReferences.add(ref); |
| } |
| } |
| } |
| |
| return sortedReferences.toArray(new IWorkbenchPartReference[sortedReferences.size()]); |
| } |
| |
| /** |
| * @see IWorkbenchPage |
| */ |
| @Override |
| public IAdaptable getInput() { |
| return input; |
| } |
| |
| /** |
| * Returns the page label. This is a combination of the page input and |
| * active perspective. |
| */ |
| @Override |
| public String getLabel() { |
| String label = WorkbenchMessages.WorkbenchPage_UnknownLabel; |
| IWorkbenchAdapter adapter = Adapters.adapt(input, IWorkbenchAdapter.class); |
| if (adapter != null) { |
| label = adapter.getLabel(input); |
| } |
| // Perspective persp = getActivePerspective(); |
| // if (persp != null) { |
| // label = NLS.bind(WorkbenchMessages.WorkbenchPage_PerspectiveFormat, |
| // label, persp.getDesc().getLabel()); |
| // } else if (deferredActivePersp != null) { |
| // label = |
| // NLS.bind(WorkbenchMessages.WorkbenchPage_PerspectiveFormat,label, |
| // deferredActivePersp.getLabel()); |
| // } |
| return label; |
| } |
| |
| /** |
| * Returns the perspective. |
| */ |
| @Override |
| public IPerspectiveDescriptor getPerspective() { |
| MPerspectiveStack ps = getPerspectiveStack(); |
| MPerspective curPersp = ps.getSelectedElement(); |
| if (curPersp == null) |
| return null; |
| return getPerspectiveDesc(curPersp.getElementId()); |
| } |
| |
| public IPerspectiveDescriptor getPerspectiveDesc(String id) { |
| IPerspectiveRegistry perspectiveRegistry = PlatformUI.getWorkbench().getPerspectiveRegistry(); |
| // registry may be null on shutdown |
| if (perspectiveRegistry == null) { |
| return null; |
| } |
| IPerspectiveDescriptor desc = perspectiveRegistry |
| .findPerspectiveWithId(id); |
| return desc; |
| } |
| |
| @Override |
| public ISelection getSelection() { |
| return selectionService.getSelection(); |
| } |
| |
| @Override |
| public ISelection getSelection(String partId) { |
| return selectionService.getSelection(partId); |
| } |
| |
| /** |
| * Returns the ids of the parts to list in the Show In... prompter. This is |
| * a List of Strings. |
| * |
| * @return the ids of the parts that should be available in the 'Show In...' |
| * prompt |
| */ |
| public ArrayList<?> getShowInPartIds() { |
| MPerspective perspective = getPerspectiveStack().getSelectedElement(); |
| return new ArrayList<>(ModeledPageLayout.getIds(perspective, |
| ModeledPageLayout.SHOW_IN_PART_TAG)); |
| } |
| |
| /** |
| * The user successfully performed a Show In... action on the specified |
| * part. Update the list of Show In items accordingly. |
| * |
| * @param partId |
| * the id of the part that the action was performed on |
| */ |
| public void performedShowIn(String partId) { |
| mruShowInPartIds.remove(partId); |
| mruShowInPartIds.add(0, partId); |
| } |
| |
| /** |
| * Sorts the given collection of show in target part ids in MRU order. |
| * |
| * @param partIds |
| * the collection of part ids to rearrange |
| */ |
| public void sortShowInPartIds(ArrayList<?> partIds) { |
| Collections.sort(partIds, new Comparator<Object>() { |
| @Override |
| public int compare(Object ob1, Object ob2) { |
| int index1 = mruShowInPartIds.indexOf(ob1); |
| int index2 = mruShowInPartIds.indexOf(ob2); |
| if (index1 != -1 && index2 == -1) |
| return -1; |
| if (index1 == -1 && index2 != -1) |
| return 1; |
| return index1 - index2; |
| } |
| }); |
| } |
| |
| /** |
| * See IWorkbenchPage. |
| */ |
| @Override |
| public IViewReference[] getViewReferences() { |
| return getViewReferences(false); |
| } |
| |
| private IViewReference[] getViewReferences(boolean allPerspectives) { |
| MPerspective perspective = getCurrentPerspective(); |
| if (perspective != null) { |
| int scope = allPerspectives ? WINDOW_SCOPE : EModelService.PRESENTATION; |
| Set<MUIElement> parts = new HashSet<>(); |
| List<MPlaceholder> placeholders = modelService.findElements(window, null, MPlaceholder.class, null, scope); |
| parts.addAll(placeholders); |
| parts.addAll(modelService.findElements(window, null, MPart.class, null, scope)); |
| List<IViewReference> visibleReferences = new ArrayList<>(); |
| for (ViewReference reference : viewReferences) { |
| MPart model = reference.getModel(); |
| // The part may be linked in either directly or via a |
| // placeholder. In the latter case we can look directly |
| // at the part's curSharedRef since we're only considering |
| // parts visible in the current perspective |
| if (parts.contains(model) && model.isToBeRendered() |
| && (model.getCurSharedRef() == null || model.getCurSharedRef().isToBeRendered())) { |
| // only rendered placeholders are valid view references |
| visibleReferences.add(reference); |
| } |
| } |
| return visibleReferences.toArray(new IViewReference[visibleReferences.size()]); |
| } |
| return new IViewReference[0]; |
| } |
| |
| /** |
| * See IWorkbenchPage. |
| */ |
| @Override |
| public IViewPart[] getViews() { |
| IViewReference[] viewReferences = getViewReferences(); |
| int length = viewReferences.length; |
| IViewPart[] views = new IViewPart[length]; |
| for (int i = 0; i < length; i++) { |
| views[i] = viewReferences[i].getView(true); |
| } |
| return views; |
| } |
| |
| |
| |
| /** |
| * See IWorkbenchPage. |
| */ |
| @Override |
| public IWorkbenchWindow getWorkbenchWindow() { |
| return legacyWindow; |
| } |
| |
| /** |
| * Implements IWorkbenchPage |
| * |
| * @see org.eclipse.ui.IWorkbenchPage#getWorkingSet() |
| * @since 2.0 |
| * @deprecated individual views should store a working set if needed |
| */ |
| @Deprecated |
| @Override |
| public IWorkingSet getWorkingSet() { |
| return workingSet; |
| } |
| |
| /** |
| * @see IWorkbenchPage |
| */ |
| @Override |
| public void hideActionSet(String actionSetID) { |
| MPerspective mpersp = getCurrentPerspective(); |
| if (mpersp == null) |
| return; |
| |
| Perspective persp = getActivePerspective(); |
| if (persp != null) { |
| ActionSetRegistry reg = WorkbenchPlugin.getDefault().getActionSetRegistry(); |
| |
| IActionSetDescriptor desc = reg.findActionSet(actionSetID); |
| if (desc != null) { |
| persp.removeActionSet(desc); |
| } |
| legacyWindow.updateActionSets(); |
| legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_ACTION_SET_HIDE); |
| } |
| String tag = ModeledPageLayout.ACTION_SET_TAG + actionSetID; |
| addHiddenItems(tag); |
| } |
| |
| @Override |
| public void hideView(IViewReference view) { |
| if (view != null) { |
| for (IViewReference reference : getViewReferences()) { |
| if (reference == view) { |
| hidePart(((ViewReference) view).getModel(), true, true, false); |
| break; |
| } |
| } |
| } |
| } |
| |
| @Override |
| public void hideView(IViewPart view) { |
| if (view != null) { |
| MPart part = findPart(view); |
| if (part != null) { |
| hidePart(part, true, true, false); |
| } |
| } |
| } |
| |
| /** |
| * Initialize the page. |
| * |
| * @param w |
| * the parent window |
| * @param layoutID |
| * may be <code>null</code> if restoring from file |
| * @param input |
| * the page input |
| * @param openExtras |
| * whether to process the perspective extras preference |
| */ |
| private void init(WorkbenchWindow w, String layoutID, IAdaptable input, boolean openExtras) { |
| // Save args. |
| this.legacyWindow = w; |
| this.input = input; |
| actionSets = new ActionSetManager(w); |
| initActionSetListener(); |
| initMaxFileSize(); |
| } |
| |
| private void initMaxFileSize() { |
| IPreferenceStore preferenceStore = PrefUtil.getInternalPreferenceStore(); |
| maxFileSize = preferenceStore.getLong(IPreferenceConstants.LARGE_DOC_SIZE_FOR_EDITORS); |
| checkDocumentSize = maxFileSize != 0; |
| } |
| |
| @PostConstruct |
| public void setup(MApplication application, EModelService modelService, IEventBroker broker, |
| MWindow window, EPartService partService) { |
| this.application = application; |
| this.modelService = modelService; |
| this.broker = broker; |
| this.window = window; |
| this.partService = partService; |
| selectionService = ContextInjectionFactory.make(SelectionService.class, window.getContext()); |
| |
| partService.addPartListener(e4PartListener); |
| |
| // create editor references for all editors |
| List<MPart> editors = modelService.findElements(window, |
| CompatibilityEditor.MODEL_ELEMENT_ID, MPart.class, null, |
| EModelService.IN_ANY_PERSPECTIVE | EModelService.OUTSIDE_PERSPECTIVE |
| | EModelService.IN_SHARED_AREA); |
| for (MPart editor : editors) { |
| createEditorReferenceForPart(editor, null, editor.getElementId(), null); |
| } |
| |
| // create view references for rendered view placeholders |
| List<MPlaceholder> placeholders = modelService.findElements(window, null, |
| MPlaceholder.class, null, EModelService.IN_ANY_PERSPECTIVE |
| | EModelService.OUTSIDE_PERSPECTIVE); |
| for (MPlaceholder placeholder : placeholders) { |
| if (placeholder.isToBeRendered()) { |
| MUIElement ref = placeholder.getRef(); |
| if (ref instanceof MPart) { |
| MPart part = (MPart) ref; |
| String uri = part.getContributionURI(); |
| if (uri.equals(CompatibilityPart.COMPATIBILITY_VIEW_URI)) { |
| createViewReferenceForPart(part, part.getElementId()); |
| } |
| } |
| } |
| } |
| |
| broker.subscribe(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT, selectionHandler); |
| broker.subscribe(UIEvents.UIElement.TOPIC_WIDGET, widgetHandler); |
| broker.subscribe(UIEvents.UIElement.TOPIC_TOBERENDERED, referenceRemovalEventHandler); |
| broker.subscribe(UIEvents.Contribution.TOPIC_OBJECT, firingHandler); |
| broker.subscribe(UIEvents.ElementContainer.TOPIC_CHILDREN, childrenHandler); |
| |
| // Bug 479126 PERSPECTIVE_BAR_EXTRAS setting not taken into account |
| createPerspectiveBarExtras(); |
| |
| MPerspectiveStack perspectiveStack = getPerspectiveStack(); |
| if (perspectiveStack != null) { |
| extendPerspectives(perspectiveStack); |
| } |
| |
| IPerspectiveRegistry registry = getWorkbenchWindow().getWorkbench() |
| .getPerspectiveRegistry(); |
| for (MPerspective perspective : perspectiveStack.getChildren()) { |
| IPerspectiveDescriptor desc = registry |
| .findPerspectiveWithId(perspective.getElementId()); |
| if (desc != null) { |
| sortedPerspectives.add(desc); |
| } |
| } |
| |
| MPerspective selectedPerspective = perspectiveStack.getSelectedElement(); |
| if (selectedPerspective != null) { |
| IPerspectiveDescriptor desc = registry.findPerspectiveWithId(selectedPerspective |
| .getElementId()); |
| if (desc != null) { |
| sortedPerspectives.remove(desc); |
| sortedPerspectives.add(desc); |
| } |
| } |
| restoreWorkingSets(); |
| restoreShowInMruPartIdsList(); |
| configureExistingWindows(); |
| } |
| |
| /* |
| * Perform any configuration required for an existing MWindow. The |
| * association of an MWindow to the WorkbenchWindow/WorkbenchPage can occur |
| * at different times (see Bug 454056 for details). |
| */ |
| private void configureExistingWindows() { |
| List<MArea> elements = modelService.findElements(window, null, MArea.class, null); |
| for (MArea area : elements) { |
| Object widget = area.getWidget(); |
| if (widget instanceof Control) { |
| installAreaDropSupport((Control) widget); |
| } |
| } |
| } |
| |
| public void restoreWorkingSets() { |
| String workingSetName = getWindowModel().getPersistedState().get( |
| IWorkbenchConstants.TAG_WORKING_SET); |
| if (workingSetName != null) { |
| AbstractWorkingSetManager workingSetManager = (AbstractWorkingSetManager) getWorkbenchWindow() |
| .getWorkbench().getWorkingSetManager(); |
| setWorkingSet(workingSetManager.getWorkingSet(workingSetName)); |
| } |
| |
| String workingSetMemString = getWindowModel().getPersistedState().get( |
| IWorkbenchConstants.TAG_WORKING_SETS); |
| if (workingSetMemString != null) { |
| IMemento workingSetMem; |
| try { |
| workingSetMem = XMLMemento.createReadRoot(new StringReader(workingSetMemString)); |
| IMemento[] workingSetChildren = workingSetMem |
| .getChildren(IWorkbenchConstants.TAG_WORKING_SET); |
| List<IWorkingSet> workingSetList = new ArrayList<>(workingSetChildren.length); |
| for (IMemento memento : workingSetChildren) { |
| IWorkingSet set = getWorkbenchWindow().getWorkbench().getWorkingSetManager() |
| .getWorkingSet(memento.getID()); |
| if (set != null) { |
| workingSetList.add(set); |
| } |
| } |
| |
| workingSets = workingSetList.toArray(new IWorkingSet[workingSetList.size()]); |
| } catch (WorkbenchException e) { |
| StatusManager.getManager().handle( |
| new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.ERROR, |
| WorkbenchMessages.WorkbenchPage_problemRestoringTitle, e)); |
| } |
| } |
| |
| aggregateWorkingSetId = getWindowModel().getPersistedState().get( |
| ATT_AGGREGATE_WORKING_SET_ID); |
| } |
| |
| private void restoreShowInMruPartIdsList() { |
| String mruList = getWindowModel().getPersistedState().get(IWorkbenchConstants.TAG_SHOW_IN_TIME); |
| if (mruList != null) { |
| try { |
| IMemento memento = XMLMemento.createReadRoot(new StringReader(mruList)); |
| IMemento[] mementoChildren = memento.getChildren(); |
| for (IMemento child : mementoChildren) { |
| mruShowInPartIds.add(child.getID()); |
| } |
| } catch (WorkbenchException e) { |
| StatusManager.getManager().handle( |
| new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.ERROR, |
| WorkbenchMessages.WorkbenchPage_problemRestoringTitle, e)); |
| } |
| } |
| } |
| |
| @PreDestroy |
| public void saveWorkingSets() { |
| // Save working set if set |
| if (workingSet != null) { |
| getWindowModel().getPersistedState().put(IWorkbenchConstants.TAG_WORKING_SET, |
| workingSet.getName()); |
| } else { |
| getWindowModel().getPersistedState().remove(IWorkbenchConstants.TAG_WORKING_SET); |
| } |
| |
| List<String> workingSetNames = new ArrayList<>(workingSets.length); |
| for (IWorkingSet workingSet : workingSets) { |
| workingSetNames.add(workingSet.getName()); |
| } |
| saveMemento(IWorkbenchConstants.TAG_WORKING_SETS, IWorkbenchConstants.TAG_WORKING_SET, workingSetNames); |
| |
| getWindowModel().getPersistedState().put(ATT_AGGREGATE_WORKING_SET_ID, |
| aggregateWorkingSetId); |
| } |
| |
| @PreDestroy |
| public void saveShowInMruPartIdsList() { |
| saveMemento(IWorkbenchConstants.TAG_SHOW_IN_TIME, IWorkbenchConstants.TAG_ID, mruShowInPartIds); |
| } |
| |
| private void saveMemento(String rootType, String childType, Collection<String> ids) { |
| XMLMemento memento = XMLMemento.createWriteRoot(rootType); |
| for (String id : ids) { |
| memento.createChild(childType, id); |
| } |
| StringWriter writer = new StringWriter(); |
| try { |
| memento.save(writer); |
| getWindowModel().getPersistedState().put(rootType, writer.getBuffer().toString()); |
| } catch (IOException e) { |
| // Simply don't store the settings |
| StatusManager.getManager().handle( |
| new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.ERROR, WorkbenchMessages.SavingProblem, e)); |
| } |
| } |
| |
| /** |
| * Extends the perspectives within the given stack with action set |
| * contributions from the <code>perspectiveExtensions</code> extension |
| * point. |
| * |
| * @param perspectiveStack |
| * the stack that contain the perspectives to be extended |
| */ |
| private void extendPerspectives(MPerspectiveStack perspectiveStack) { |
| for (MPerspective perspective : perspectiveStack.getChildren()) { |
| String id = perspective.getElementId(); |
| IPerspectiveDescriptor desc = getWorkbenchWindow().getWorkbench() |
| .getPerspectiveRegistry().findPerspectiveWithId(id); |
| if (desc != null) { |
| MPerspective temporary = modelService.createModelElement(MPerspective.class); |
| ModeledPageLayout modelLayout = new ModeledPageLayout(window, modelService, |
| partService, temporary, desc, this, true); |
| |
| PerspectiveExtensionReader reader = new PerspectiveExtensionReader(); |
| reader.setIncludeOnlyTags(new String[] { IWorkbenchRegistryConstants.TAG_ACTION_SET }); |
| reader.extendLayout(null, id, modelLayout); |
| |
| addActionSet(perspective, temporary); |
| } |
| } |
| } |
| |
| ArrayList<String> getPerspectiveExtensionActionSets(String id) { |
| IPerspectiveDescriptor desc = getWorkbenchWindow().getWorkbench().getPerspectiveRegistry() |
| .findPerspectiveWithId(id); |
| if (desc != null) { |
| MPerspective temporary = modelService.createModelElement(MPerspective.class); |
| ModeledPageLayout modelLayout = new ModeledPageLayout(window, modelService, |
| partService, temporary, desc, this, true); |
| |
| PerspectiveExtensionReader reader = new PerspectiveExtensionReader(); |
| reader.setIncludeOnlyTags(new String[] { IWorkbenchRegistryConstants.TAG_ACTION_SET }); |
| reader.extendLayout(null, id, modelLayout); |
| return new ArrayList<>(ModeledPageLayout.getIds(temporary, ModeledPageLayout.ACTION_SET_TAG)); |
| } |
| return null; |
| } |
| |
| /** |
| * Copies action set extensions from the temporary perspective to the other |
| * one. |
| * |
| * @param perspective |
| * the perspective to copy action set contributions to |
| * @param temporary |
| * the perspective to copy action set contributions from |
| */ |
| private void addActionSet(MPerspective perspective, MPerspective temporary) { |
| List<String> tags = perspective.getTags(); |
| List<String> extendedTags = temporary.getTags(); |
| for (String extendedTag : extendedTags) { |
| if (!tags.contains(extendedTag)) { |
| tags.add(extendedTag); |
| } |
| } |
| } |
| |
| /** |
| * Installs drop support into the shared area so that editors can be opened |
| * by dragging and dropping files into it. |
| * |
| * @param control |
| * the control to attach the drop support to |
| */ |
| private void installAreaDropSupport(Control control) { |
| if (!dndSupportInstalled) { |
| WorkbenchWindowConfigurer configurer = legacyWindow.getWindowConfigurer(); |
| DropTargetListener dropTargetListener = configurer.getDropTargetListener(); |
| if (dropTargetListener != null) { |
| DropTarget dropTarget = new DropTarget(control, DND.DROP_DEFAULT | DND.DROP_COPY |
| | DND.DROP_LINK); |
| dropTarget.setTransfer(configurer.getTransfers()); |
| dropTarget.addDropListener(dropTargetListener); |
| } |
| dndSupportInstalled = true; |
| } |
| } |
| |
| private List<MPartStack> getPartStacks(MPerspective perspective) { |
| if (perspective == null) { |
| return Collections.emptyList(); |
| } |
| return modelService.findElements(perspective, null, MPartStack.class, null); |
| } |
| |
| private EventHandler selectionHandler = new EventHandler() { |
| @Override |
| public void handleEvent(Event event) { |
| Object changedElement = event.getProperty(UIEvents.EventTags.ELEMENT); |
| |
| if (!(changedElement instanceof MPerspectiveStack)) { |
| return; |
| } |
| |
| List<MPerspectiveStack> theStack = modelService.findElements(window, null, |
| MPerspectiveStack.class, null); |
| if (theStack.isEmpty()) { |
| return; |
| } else if (!theStack.isEmpty() && changedElement != theStack.get(0)) { |
| return; |
| } |
| |
| MPerspective oldPersp = (MPerspective) event.getProperty(UIEvents.EventTags.OLD_VALUE); |
| MPerspective newPersp = (MPerspective) event.getProperty(UIEvents.EventTags.NEW_VALUE); |
| // updatePerspectiveActionSets(oldPersp, newPersp); |
| |
| // ((CoolBarToTrimManager) |
| // legacyWindow.getCoolBarManager2()).updateAll(true); |
| // legacyWindow.menuManager.updateAll(true); |
| |
| List<MPart> hiddenParts = new ArrayList<>(); |
| List<MPart> visibleParts = new ArrayList<>(); |
| |
| List<MPartStack> oldStacks = getPartStacks(oldPersp); |
| List<MPartStack> newStacks = getPartStacks(newPersp); |
| |
| for (MPartStack oldStack : oldStacks) { |
| MStackElement element = oldStack.getSelectedElement(); |
| if (element instanceof MPlaceholder) { |
| hiddenParts.add((MPart) ((MPlaceholder) element).getRef()); |
| } else if (element instanceof MPart) { |
| hiddenParts.add((MPart) element); |
| } |
| } |
| |
| for (MPartStack newStack : newStacks) { |
| MStackElement element = newStack.getSelectedElement(); |
| if (element instanceof MPlaceholder) { |
| visibleParts.add((MPart) ((MPlaceholder) element).getRef()); |
| } else if (element instanceof MPart) { |
| visibleParts.add((MPart) element); |
| } |
| } |
| |
| List<MPart> ignoredParts = new ArrayList<>(); |
| for (MPart hiddenPart : hiddenParts) { |
| if (visibleParts.contains(hiddenPart)) { |
| ignoredParts.add(hiddenPart); |
| } |
| } |
| |
| hiddenParts.removeAll(ignoredParts); |
| visibleParts.removeAll(ignoredParts); |
| |
| for (MPart hiddenPart : hiddenParts) { |
| firePartHidden(hiddenPart); |
| } |
| |
| for (MPart visiblePart : visibleParts) { |
| firePartVisible(visiblePart); |
| } |
| |
| updateActionSets(getPerspective(oldPersp), getPerspective(newPersp)); |
| |
| // might've been set to null if we were closing the perspective |
| if (newPersp != null) { |
| IPerspectiveDescriptor perspective = getPerspectiveDesc(newPersp |
| .getElementId()); |
| legacyWindow.firePerspectiveActivated(WorkbenchPage.this, perspective); |
| |
| sortedPerspectives.remove(perspective); |
| sortedPerspectives.add(perspective); |
| } |
| legacyWindow.updateActionSets(); |
| } |
| }; |
| |
| /** |
| * See IWorkbenchPage. |
| */ |
| @Override |
| public boolean isPartVisible(IWorkbenchPart part) { |
| MPart mpart = findPart(part); |
| return mpart == null ? false : partService.isPartVisible(mpart); |
| } |
| |
| public MUIElement findSharedArea() { |
| MPerspective perspective = getPerspectiveStack().getSelectedElement(); |
| return perspective == null ? null : modelService.find(IPageLayout.ID_EDITOR_AREA, |
| perspective); |
| } |
| |
| /** |
| * See IWorkbenchPage. |
| */ |
| @Override |
| public boolean isEditorAreaVisible() { |
| MUIElement find = findSharedArea(); |
| return find == null ? false : find.isVisible() && find.isToBeRendered(); |
| } |
| |
| @Override |
| public boolean isPageZoomed() { |
| List<String> maxTag = new ArrayList<>(); |
| maxTag.add(IPresentationEngine.MAXIMIZED); |
| List<Object> maxElements = modelService.findElements(window, null, null, maxTag); |
| return maxElements.size() > 0; |
| } |
| |
| |
| // /** |
| // * This method is called when the page is activated. |
| // */ |
| // protected void onActivate() { |
| // composite.setVisible(true); |
| // Perspective persp = getActivePerspective(); |
| // |
| // if (persp != null) { |
| // persp.onActivate(); |
| // updateVisibility(null, persp); |
| // } |
| // } |
| // |
| // /** |
| // * This method is called when the page is deactivated. |
| // */ |
| // protected void onDeactivate() { |
| // makeActiveEditor(null); |
| // makeActive(null); |
| // if (getActivePerspective() != null) { |
| // getActivePerspective().onDeactivate(); |
| // } |
| // composite.setVisible(false); |
| // } |
| |
| /** |
| * See IWorkbenchPage. |
| */ |
| @Override |
| public void reuseEditor(IReusableEditor editor, IEditorInput input) { |
| |
| // Rather than calling editor.setInput on the editor directly, we do it through the part reference. |
| // This case lets us detect badly behaved editors that are not firing a PROP_INPUT event in response |
| // to the input change... but if all editors obeyed their API contract, the "else" branch would be |
| // sufficient. |
| |
| // TODO compat: should we be talking to the editor reference here |
| editor.setInput(input); |
| navigationHistory.markEditor(editor); |
| } |
| |
| /** |
| * See IWorkbenchPage. |
| */ |
| @Override |
| public IEditorPart openEditor(IEditorInput input, String editorID) |
| throws PartInitException { |
| return openEditor(input, editorID, true, MATCH_INPUT); |
| } |
| |
| /** |
| * See IWorkbenchPage. |
| */ |
| @Override |
| public IEditorPart openEditor(IEditorInput input, String editorID, |
| boolean activate) throws PartInitException { |
| return openEditor(input, editorID, activate, MATCH_INPUT); |
| } |
| |
| /** |
| * See IWorkbenchPage. |
| */ |
| @Override |
| public IEditorPart openEditor(final IEditorInput input, |
| final String editorID, final boolean activate, final int matchFlags) |
| throws PartInitException { |
| return openEditor(input, editorID, activate, matchFlags, null, true); |
| } |
| |
| /** |
| * This is not public API but for use internally. editorState can be |
| * <code>null</code>. |
| * |
| * @param input |
| * the input to open the editor with |
| * @param editorID |
| * the id of the editor to open |
| * @param activate |
| * <tt>true</tt> if the editor should be activated, |
| * <tt>false</tt> otherwise |
| * @param matchFlags |
| * a bit mask consisting of zero or more of the MATCH_* constants |
| * OR-ed together |
| * @param editorState |
| * the previously saved state of the editor as a memento, this |
| * may be <tt>null</tt> |
| * @param notify |
| * <tt>true</tt> if the perspective should fire off events about |
| * the editors being opened, <tt>false</tt> otherwise |
| * @return the opened editor |
| * @exception PartInitException |
| * if the editor could not be created or initialized |
| */ |
| public IEditorPart openEditor(final IEditorInput input, final String editorID, |
| final boolean activate, final int matchFlags, final IMemento editorState, |
| final boolean notify) throws PartInitException { |
| if (input == null || editorID == null) { |
| throw new IllegalArgumentException(); |
| } |
| |
| final IEditorPart result[] = new IEditorPart[1]; |
| final PartInitException ex[] = new PartInitException[1]; |
| BusyIndicator.showWhile(legacyWindow.getWorkbench().getDisplay(), |
| new Runnable() { |
| @Override |
| public void run() { |
| try { |
| result[0] = busyOpenEditor(input, editorID, activate, matchFlags, editorState, |
| notify); |
| } catch (PartInitException e) { |
| ex[0] = e; |
| } |
| } |
| }); |
| if (ex[0] != null) { |
| throw ex[0]; |
| } |
| return result[0]; |
| } |
| |
| |
| |
| /** |
| * @see #openEditor(IEditorInput, String, boolean, int) |
| */ |
| private IEditorPart busyOpenEditor(IEditorInput input, String editorId, boolean activate, |
| int matchFlags, IMemento editorState, boolean notify) throws PartInitException { |
| |
| if (input == null || editorId == null) { |
| throw new IllegalArgumentException(); |
| } |
| |
| // Special handling for external editors (they have no tabs...) |
| if ("org.eclipse.ui.systemExternalEditor".equals(editorId)) { //$NON-NLS-1$ |
| IPathEditorInput fileInput = getPathEditorInput(input); |
| if (fileInput == null) { |
| throw new PartInitException(WorkbenchMessages.EditorManager_systemEditorError); |
| } |
| |
| String fullPath = fileInput.getPath().toOSString(); |
| Program.launch(fullPath); |
| return null; |
| } |
| |
| IEditorDescriptor desc = getWorkbenchWindow().getWorkbench() |
| .getEditorRegistry().findEditor(editorId); |
| if (desc != null && !desc.isOpenExternal() && isLargeDocument(input)) { |
| desc = getAlternateEditor(); |
| if (desc == null) { |
| // the user pressed cancel in the editor selection dialog |
| return null; |
| } |
| } |
| if (desc == null) { |
| throw new PartInitException(NLS.bind( |
| WorkbenchMessages.EditorManager_unknownEditorIDMessage, editorId)); |
| } |
| |
| setEditorAreaVisible(true); |
| |
| IEditorReference[] editorReferences = findEditors(input, editorId, matchFlags); |
| if (editorReferences.length != 0) { |
| IEditorPart editor = editorReferences[0].getEditor(true); |
| if (editor instanceof IShowEditorInput) { |
| ((IShowEditorInput) editor).showEditorInput(input); |
| } |
| |
| partService.showPart(((EditorReference) editorReferences[0]).getModel(), |
| PartState.VISIBLE); |
| |
| if (activate) { |
| activate(editor); |
| } |
| |
| recordEditor(input, desc); |
| return editor; |
| } else if (desc.isInternal()) { |
| // look for an editor to reuse |
| EditorReference reusableEditorRef = (EditorReference) ((TabBehaviour) Tweaklets |
| .get(TabBehaviour.KEY)).findReusableEditor(this); |
| if (reusableEditorRef != null) { |
| IEditorPart reusableEditor = reusableEditorRef.getEditor(false); |
| if (editorId.equals(reusableEditorRef.getId()) |
| && reusableEditor instanceof IReusableEditor) { |
| // reusable editors that share the same id are okay |
| recordEditor(input, desc); |
| reuseEditor((IReusableEditor) reusableEditor, input); |
| |
| MPart editor = reusableEditorRef.getModel(); |
| partService.showPart(editor, PartState.VISIBLE); |
| if (activate) { |
| partService.activate(editor); |
| } else { |
| updateActiveEditorSources(editor); |
| } |
| return reusableEditor; |
| } |
| // should have saved already if necessary, close this editor, a |
| // new one will be opened |
| closeEditor(reusableEditorRef, false); |
| } |
| } else if (desc.isOpenExternal()) { |
| openExternalEditor((EditorDescriptor) desc, input); |
| // no editor parts for external editors, return null |
| return null; |
| } |
| |
| MPart editor = partService.createPart(CompatibilityEditor.MODEL_ELEMENT_ID); |
| editor.getTags().add(editorId); |
| EditorReference ref = createEditorReferenceForPart(editor, input, editorId, editorState); |
| partService.showPart(editor, PartState.VISIBLE); |
| |
| CompatibilityEditor compatibilityEditor = (CompatibilityEditor) editor.getObject(); |
| if (compatibilityEditor == null) { |
| return null; |
| } |
| |
| if (activate) { |
| partService.activate(editor); |
| } else { |
| updateActiveEditorSources(editor); |
| } |
| |
| if (notify) { |
| legacyWindow.firePerspectiveChanged(this, getPerspective(), ref, CHANGE_EDITOR_OPEN); |
| legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_EDITOR_OPEN); |
| } |
| |
| recordEditor(input, desc); |
| return compatibilityEditor.getEditor(); |
| } |
| |
| private void recordEditor(IEditorInput input, IEditorDescriptor descriptor) { |
| EditorHistory history = ((Workbench) legacyWindow.getWorkbench()).getEditorHistory(); |
| history.add(input, descriptor); |
| } |
| |
| private static IEditorDescriptor getAlternateEditor() { |
| Shell shell = ProgressManagerUtil.getDefaultParent(); |
| EditorSelectionDialog dialog = new EditorSelectionDialog(shell) { |
| @Override |
| protected IDialogSettings getDialogSettings() { |
| IDialogSettings result = new DialogSettings("EditorSelectionDialog"); //$NON-NLS-1$ |
| result.put(EditorSelectionDialog.STORE_ID_INTERNAL_EXTERNAL, true); |
| return result; |
| } |
| }; |
| dialog.setMessage(WorkbenchMessages.EditorManager_largeDocumentWarning); |
| |
| if (dialog.open() == Window.OK) |
| return dialog.getSelectedEditor(); |
| return null; |
| } |
| |
| boolean isLargeDocument(IEditorInput editorInput) { |
| |
| if (!checkDocumentSize) |
| return false; |
| |
| if (!(editorInput instanceof IPathEditorInput)) |
| return false; // we know nothing about it |
| |
| try { |
| IPath path = ((IPathEditorInput) editorInput).getPath(); |
| File file = new File(path.toOSString()); |
| return file.length() > maxFileSize; |
| } catch (Exception e) { |
| // ignore exceptions |
| return false; |
| } |
| } |
| |
| /** |
| * See IWorkbenchPage. |
| */ |
| @Override |
| public boolean isEditorPinned(IEditorPart editor) { |
| WorkbenchPartReference ref = (WorkbenchPartReference)getReference(editor); |
| return ref != null && ref.isPinned(); |
| } |
| |
| |
| |
| /** |
| * Removes an IPartListener from the part service. |
| */ |
| @Override |
| public void removePartListener(IPartListener l) { |
| partListenerList.remove(l); |
| } |
| |
| /** |
| * Removes an IPartListener from the part service. |
| */ |
| @Override |
| public void removePartListener(IPartListener2 l) { |
| partListener2List.remove(l); |
| } |
| |
| /** |
| * Implements IWorkbenchPage |
| * |
| * @see org.eclipse.ui.IWorkbenchPage#removePropertyChangeListener(IPropertyChangeListener) |
| * @since 2.0 |
| * @deprecated individual views should store a working set if needed and |
| * register a property change listener directly with the |
| * working set manager to receive notification when the view |
| * working set is removed. |
| */ |
| @Deprecated |
| @Override |
| public void removePropertyChangeListener(IPropertyChangeListener listener) { |
| propertyChangeListeners.remove(listener); |
| } |
| |
| @Override |
| public void removeSelectionListener(ISelectionListener listener) { |
| selectionService.removeSelectionListener(listener); |
| } |
| |
| @Override |
| public void removeSelectionListener(String partId, |
| ISelectionListener listener) { |
| selectionService.removeSelectionListener(partId, listener); |
| } |
| |
| @Override |
| public void removePostSelectionListener(ISelectionListener listener) { |
| selectionService.removePostSelectionListener(listener); |
| } |
| |
| @Override |
| public void removePostSelectionListener(String partId, |
| ISelectionListener listener) { |
| selectionService.removePostSelectionListener(partId, listener); |
| } |
| |
| |
| |
| /** |
| * Resets the layout for the perspective. The active part in the old layout |
| * is activated in the new layout for consistent user context. |
| */ |
| @Override |
| public void resetPerspective() { |
| MPerspectiveStack perspStack = getPerspectiveStack(); |
| MPerspective persp = perspStack.getSelectedElement(); |
| if (persp == null) |
| return; |
| |
| // HACK!! the 'perspective' field doesn't match reality... |
| IPerspectiveDescriptor desc = PlatformUI.getWorkbench().getPerspectiveRegistry() |
| .findPerspectiveWithId(persp.getElementId()); |
| if (desc == null) |
| return; |
| |
| // send out reset notification |
| legacyWindow.firePerspectiveChanged(this, desc, CHANGE_RESET); |
| |
| // collect all the parts under the current perspective |
| List<MPart> perspectiveParts = modelService.findElements(persp, null, MPart.class, null); |
| // find the shared area |
| MUIElement area = findSharedArea(); |
| if (area != null) { |
| // remove all editors in the shared area from the list of parts |
| perspectiveParts.removeAll(modelService.findElements(area, |
| CompatibilityEditor.MODEL_ELEMENT_ID, MPart.class, null)); |
| } |
| |
| List<MPart> dirtyParts = new ArrayList<>(); |
| List<IWorkbenchPart> partsToSave = new ArrayList<>(); |
| // iterate over the list of parts to find dirty parts |
| for (MPart currentPart : perspectiveParts) { |
| if (currentPart.isDirty()) { |
| Object object = currentPart.getObject(); |
| if (object == null) { |
| continue; |
| } else if (object instanceof CompatibilityPart) { |
| IWorkbenchPart workbenchPart = ((CompatibilityPart) object).getPart(); |
| ISaveablePart saveable = SaveableHelper.getSaveable(workbenchPart); |
| if (saveable == null || !saveable.isSaveOnCloseNeeded()) { |
| continue; |
| } |
| partsToSave.add(workbenchPart); |
| } |
| |
| dirtyParts.add(currentPart); |
| } |
| } |
| |
| SaveablesList saveablesList = null; |
| Object postCloseInfo = null; |
| if (partsToSave.size() > 0) { |
| saveablesList = (SaveablesList) getWorkbenchWindow().getService( |
| ISaveablesLifecycleListener.class); |
| postCloseInfo = saveablesList.preCloseParts(partsToSave, true, |
| this.getWorkbenchWindow()); |
| if (postCloseInfo == null) { |
| // cancel |
| // We're not going through with the reset, so it is |
| // complete. |
| legacyWindow.firePerspectiveChanged(this, desc, CHANGE_RESET_COMPLETE); |
| return; |
| } |
| } |
| |
| modelService.resetPerspectiveModel(persp, window); |
| |
| if (saveablesList != null) { |
| saveablesList.postClose(postCloseInfo); |
| } |
| |
| boolean revert = false; |
| if (desc instanceof PerspectiveDescriptor) { |
| PerspectiveDescriptor perspectiveDescriptor = (PerspectiveDescriptor) desc; |
| revert = perspectiveDescriptor.isPredefined() |
| && !perspectiveDescriptor.hasCustomDefinition(); |
| } |
| |
| MPerspective dummyPerspective = null; |
| if (!revert) { |
| dummyPerspective = (MPerspective) modelService.cloneSnippet(application, desc.getId(), |
| window); |
| if (dummyPerspective != null) { |
| handleNullRefPlaceHolders(dummyPerspective, window); |
| } |
| } |
| |
| if (dummyPerspective == null) { |
| // instantiate a dummy perspective perspective |
| dummyPerspective = modelService.createModelElement(MPerspective.class); |
| dummyPerspective.setElementId(persp.getElementId()); |
| |
| IPerspectiveFactory factory = ((PerspectiveDescriptor) desc).createFactory(); |
| ModeledPageLayout modelLayout = new ModeledPageLayout(window, modelService, |
| partService, dummyPerspective, desc, this, true); |
| factory.createInitialLayout(modelLayout); |
| |
| PerspectiveTagger.tagPerspective(dummyPerspective, modelService); |
| PerspectiveExtensionReader reader = new PerspectiveExtensionReader(); |
| reader.extendLayout(getExtensionTracker(), desc.getId(), modelLayout); |
| } |
| |
| String hiddenItems = dummyPerspective.getPersistedState().get(ModeledPageLayout.HIDDEN_ITEMS_KEY); |
| persp.getPersistedState().put(ModeledPageLayout.HIDDEN_ITEMS_KEY, hiddenItems); |
| |
| legacyWindow.getMenuManager().updateAll(true); |
| // ((ICoolBarManager2) ((WorkbenchWindow) |
| // getWorkbenchWindow()).getCoolBarManager2()) |
| // .resetItemOrder(); |
| |
| // Hide placeholders for parts that exist in the 'global' areas |
| modelService.hideLocalPlaceholders(window, dummyPerspective); |
| |
| int dCount = dummyPerspective.getChildren().size(); |
| while (dummyPerspective.getChildren().size() > 0) { |
| MPartSashContainerElement dChild = dummyPerspective.getChildren().remove(0); |
| persp.getChildren().add(dChild); |
| } |
| |
| while (persp.getChildren().size() > dCount) { |
| MUIElement child = persp.getChildren().get(0); |
| child.setToBeRendered(false); |
| persp.getChildren().remove(0); |
| } |
| |
| List<MWindow> existingDetachedWindows = new ArrayList<>(); |
| existingDetachedWindows.addAll(persp.getWindows()); |
| |
| // Move any detached windows from template to perspective |
| while (dummyPerspective.getWindows().size() > 0) { |
| MWindow detachedWindow = dummyPerspective.getWindows().remove(0); |
| persp.getWindows().add(detachedWindow); |
| } |
| |
| // Remove original windows. Can't remove them first or the MParts will be disposed |
| for (MWindow detachedWindow : existingDetachedWindows) { |
| detachedWindow.setToBeRendered(false); |
| persp.getWindows().remove(detachedWindow); |
| } |
| |
| // deactivate and activate other action sets as |
| Perspective oldPersp = getPerspective(persp); |
| Perspective dummyPersp = getPerspective(dummyPerspective); |
| updateActionSets(oldPersp, dummyPersp); |
| oldPersp.getAlwaysOnActionSets().clear(); |
| oldPersp.getAlwaysOnActionSets().addAll(dummyPersp.getAlwaysOnActionSets()); |
| oldPersp.getAlwaysOffActionSets().clear(); |
| oldPersp.getAlwaysOffActionSets().addAll(dummyPersp.getAlwaysOffActionSets()); |
| |
| modelToPerspectiveMapping.remove(dummyPerspective); |
| |
| // partly fixing toolbar refresh issue, see bug 383569 comment 10 |
| legacyWindow.updateActionSets(); |
| |
| // migrate the tags |
| List<String> tags = persp.getTags(); |
| tags.clear(); |
| tags.addAll(dummyPerspective.getTags()); |
| |
| // remove HIDDEN_EXPLICITLY tag from trim elements |
| List<MTrimElement> trimElements = modelService.findElements(window, null, |
| MTrimElement.class, null); |
| for (MTrimElement mTrimElement : trimElements) { |
| mTrimElement.getTags().remove(IPresentationEngine.HIDDEN_EXPLICITLY); |
| } |
| |
| partService.requestActivation(); |
| |
| // reset complete |
| legacyWindow.firePerspectiveChanged(this, desc, CHANGE_RESET_COMPLETE); |
| UIEvents.publishEvent(UIEvents.UILifeCycle.PERSPECTIVE_RESET, persp); |
| } |
| |
| private void initActionSetListener() { |
| // actionSets.addListener(new IPropertyListener() { |
| // public void propertyChanged(Object source, int propId) { |
| // if (source instanceof IActionSetDescriptor) { |
| // final IActionSetDescriptor desc = (IActionSetDescriptor) source; |
| // final String actionSetId = ModeledPageLayout.ACTION_SET_TAG + |
| // desc.getId(); |
| // final MPerspective currentPerspective = getCurrentPerspective(); |
| // if (currentPerspective != null) { |
| // final List<String> tags = currentPerspective.getTags(); |
| // if (propId == ActionSetManager.PROP_VISIBLE) { |
| // if (!tags.contains(actionSetId)) { |
| // tags.add(actionSetId); |
| // } |
| // } else if (propId == ActionSetManager.PROP_HIDDEN) { |
| // tags.remove(actionSetId); |
| // } |
| // } |
| // } |
| // } |
| // }); |
| } |
| |
| /** |
| * See IWorkbenchPage |
| */ |
| @Override |
| public boolean saveAllEditors(boolean confirm) { |
| return saveAllEditors(confirm, false, false); |
| } |
| |
| /** |
| * @return {@link ISaveablePart} objects derived from {@link IWorkbenchPart} |
| * 's on this page |
| */ |
| public ISaveablePart[] getDirtyParts() { |
| List<ISaveablePart> result = new ArrayList<>(3); |
| IWorkbenchPartReference[] allParts = getSortedParts(true, true, true); |
| for (IWorkbenchPartReference reference : allParts) { |
| IWorkbenchPart part = reference.getPart(false); |
| ISaveablePart saveable = SaveableHelper.getSaveable(part); |
| if (saveable != null && !result.contains(saveable)) { |
| if (saveable.isDirty()) { |
| result.add(saveable); |
| } |
| } |
| } |
| return result.toArray(new ISaveablePart[result.size()]); |
| } |
| |
| /** |
| * @return workbench parts which are dirty (implement or adapt to |
| * {@link ISaveablePart}). Only parts matching different saveables |
| * are returned. |
| */ |
| public IWorkbenchPart[] getDirtyWorkbenchParts() { |
| List<IWorkbenchPart> result = new ArrayList<>(3); |
| Map<ISaveablePart, IWorkbenchPart> saveables = new LinkedHashMap<>(3); |
| IWorkbenchPartReference[] allParts = getSortedParts(true, true, true); |
| for (IWorkbenchPartReference reference : allParts) { |
| IWorkbenchPart part = reference.getPart(false); |
| ISaveablePart saveable = SaveableHelper.getSaveable(part); |
| if (saveable == null || !saveable.isDirty()) { |
| continue; |
| } |
| IWorkbenchPart previousPart = saveables.get(saveable); |
| if (previousPart != null) { |
| // We have already a part claiming to handle this saveable. |
| // See bug 470076 where a property view might return |
| // saveable which is in turn just editor part |
| if (previousPart == saveable) { |
| // if the previous part matches saveable, we have a |
| // perfect match already |
| continue; |
| } |
| // if parts provide adapters to same saveable but |
| // saveable itself is not a part, we can try to keep |
| // editors and skip views |
| if (part != saveable && previousPart instanceof IEditorPart) { |
| continue; |
| } |
| // last part wins, since we don't want to return multiple parts |
| // representing same saveables |
| result.remove(previousPart); |
| } |
| result.add(part); |
| saveables.put(saveable, part); |
| } |
| return result.toArray(new IWorkbenchPart[result.size()]); |
| } |
| |
| public boolean saveAllEditors(boolean confirm, boolean closing, boolean addNonPartSources) { |
| IWorkbenchPart[] parts = getDirtyWorkbenchParts(); |
| if (parts.length == 0) { |
| return true; |
| } |
| // saveAll below expects a mutable list |
| List<IWorkbenchPart> dirtyParts = new ArrayList<>(parts.length); |
| for (IWorkbenchPart part : parts) { |
| dirtyParts.add(part); |
| } |
| |
| // If confirmation is required .. |
| return saveAll(dirtyParts, confirm, closing, addNonPartSources, legacyWindow, legacyWindow); |
| } |
| |
| public static boolean saveAll(List<IWorkbenchPart> dirtyParts, final boolean confirm, final boolean closing, |
| boolean addNonPartSources, final IRunnableContext runnableContext, |
| final IWorkbenchWindow workbenchWindow) { |
| // clone the input list |
| dirtyParts = new ArrayList<>(dirtyParts); |
| |
| if (closing) { |
| // if the parts are going to be closed, then we only save those that |
| // need to be saved when closed, see bug 272070 |
| removeSaveOnCloseNotNeededParts(dirtyParts); |
| } |
| |
| SaveablesList saveablesList = (SaveablesList) PlatformUI.getWorkbench().getService( |
| ISaveablesLifecycleListener.class); |
| if (confirm) { |
| return processSaveable2(dirtyParts) ? false : saveablesList.preCloseParts(dirtyParts, true, true, |
| workbenchWindow, workbenchWindow) != null; |
| } |
| List<Saveable> modelsToSave = convertToSaveables(dirtyParts, closing, addNonPartSources); |
| return modelsToSave.isEmpty() ? true : !saveablesList.saveModels(modelsToSave, workbenchWindow, |
| runnableContext, closing); |
| |
| } |
| |
| /** |
| * Removes from the provided list parts that don't need to be saved on |
| * close. |
| * |
| * @param parts |
| * the list of the parts (ISaveablePart) |
| */ |
| private static void removeSaveOnCloseNotNeededParts(List<IWorkbenchPart> parts) { |
| for (Iterator<IWorkbenchPart> it = parts.iterator(); it.hasNext();) { |
| IWorkbenchPart part = it.next(); |
| ISaveablePart saveable = SaveableHelper.getSaveable(part); |
| if (saveable == null || !saveable.isSaveOnCloseNeeded()) { |
| it.remove(); |
| } |
| } |
| } |
| |
| /** |
| * Processes all parts that implement ISaveablePart2 and removes them from |
| * the list. |
| * |
| * @param dirtyParts |
| * the list of the parts |
| * @return true if cancelled |
| */ |
| private static boolean processSaveable2(List<IWorkbenchPart> dirtyParts) { |
| boolean saveable2Processed = false; |
| // Process all parts that implement ISaveablePart2. |
| // These parts are removed from the list after saving |
| // them. We then need to restore the workbench to |
| // its previous state, for now this is just last |
| // active perspective. |
| // Note that the given parts may come from multiple |
| // windows, pages and perspectives. |
| ListIterator<IWorkbenchPart> listIterator = dirtyParts.listIterator(); |
| |
| WorkbenchPage currentPage = null; |
| Perspective currentPageOriginalPerspective = null; |
| while (listIterator.hasNext()) { |
| IWorkbenchPart part = listIterator.next(); |
| ISaveablePart2 saveable2 = SaveableHelper.getSaveable2(part); |
| if (saveable2 != null) { |
| WorkbenchPage page = (WorkbenchPage) part.getSite().getPage(); |
| if (!Util.equals(currentPage, page)) { |
| if (currentPage != null && currentPageOriginalPerspective != null) { |
| if (!currentPageOriginalPerspective.equals(currentPage |
| .getActivePerspective())) { |
| currentPage |
| .setPerspective(currentPageOriginalPerspective.getDesc()); |
| } |
| } |
| currentPage = page; |
| currentPageOriginalPerspective = page.getActivePerspective(); |
| } |
| page.bringToTop(part); |
| // try to save the part |
| int choice = SaveableHelper.savePart(saveable2, page.getWorkbenchWindow(), true); |
| if (choice == ISaveablePart2.CANCEL) { |
| // If the user cancels, don't restore the previous |
| // workbench state, as that will |
| // be an unexpected switch from the current state. |
| return true; |
| } else if (choice != ISaveablePart2.DEFAULT) { |
| saveable2Processed = true; |
| listIterator.remove(); |
| } |
| } |
| } |
| |
| // try to restore the workbench to its previous state |
| if (currentPage != null && currentPageOriginalPerspective != null) { |
| if (!currentPageOriginalPerspective.equals(currentPage.getActivePerspective())) { |
| currentPage.setPerspective(currentPageOriginalPerspective.getDesc()); |
| } |
| } |
| |
| // if processing a ISaveablePart2 caused other parts to be |
| // saved, remove them from the list presented to the user. |
| if (saveable2Processed) { |
| removeNonDirtyParts(dirtyParts); |
| } |
| |
| return false; |
| } |
| |
| private static void removeNonDirtyParts(List<IWorkbenchPart> parts) { |
| ListIterator<IWorkbenchPart> listIterator; |
| listIterator = parts.listIterator(); |
| while (listIterator.hasNext()) { |
| ISaveablePart part = SaveableHelper.getSaveable(listIterator.next()); |
| if (part == null || !part.isDirty()) { |
| listIterator.remove(); |
| } |
| } |
| } |
| |
| /** |
| * For each part (view or editor) in the given list, attempts to convert it |
| * to one or more saveable models. Duplicate models are removed. If closing |
| * is true, then models that will remain open in parts other than the given |
| * parts are removed. |
| * |
| * @param parts |
| * the parts (list of IViewPart or IEditorPart) |
| * @param closing |
| * whether the parts are being closed |
| * @param addNonPartSources |
| * whether non-part sources should be added (true for the Save |
| * All action, see bug 139004) |
| * @return the dirty models |
| */ |
| private static List<Saveable> convertToSaveables(List<IWorkbenchPart> parts, boolean closing, |
| boolean addNonPartSources) { |
| ArrayList<Saveable> result = new ArrayList<>(); |
| HashSet<Saveable> seen = new HashSet<>(); |
| for (IWorkbenchPart part : parts) { |
| for (Saveable saveable : getSaveables(part)) { |
| if (saveable.isDirty() && !seen.contains(saveable)) { |
| seen.add(saveable); |
| if (!closing |
| || closingLastPartShowingModel(saveable, parts, part.getSite() |
| .getPage())) { |
| result.add(saveable); |
| } |
| } |
| } |
| } |
| if (addNonPartSources) { |
| SaveablesList saveablesList = (SaveablesList) PlatformUI.getWorkbench().getService( |
| ISaveablesLifecycleListener.class); |
| ISaveablesSource[] nonPartSources = saveablesList.getNonPartSources(); |
| for (ISaveablesSource nonPartSource : nonPartSources) { |
| for (Saveable saveable : nonPartSource.getSaveables()) { |
| if (saveable.isDirty() && !seen.contains(saveable)) { |
| seen.add(saveable); |
| result.add(saveable); |
| } |
| } |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Returns the saveable models provided by the given part. If the part does |
| * not provide any models, a default model is returned representing the |
| * part. |
| * |
| * @param part |
| * the workbench part |
| * @return the saveable models |
| */ |
| private static Saveable[] getSaveables(IWorkbenchPart part) { |
| if (part instanceof ISaveablesSource) { |
| ISaveablesSource source = (ISaveablesSource) part; |
| return source.getSaveables(); |
| } |
| return new Saveable[] { new DefaultSaveable(part) }; |
| } |
| |
| /** |
| * Returns true if, in the given page, no more parts will reference the |
| * given model if the given parts are closed. |
| * |
| * @param model |
| * the model |
| * @param closingParts |
| * the parts being closed (list of IViewPart or IEditorPart) |
| * @param page |
| * the page |
| * @return <code>true</code> if no more parts in the page will reference the |
| * given model, <code>false</code> otherwise |
| */ |
| private static boolean closingLastPartShowingModel(Saveable model, List<IWorkbenchPart> closingParts, |
| IWorkbenchPage page) { |
| HashSet<IWorkbenchPart> closingPartsWithSameModel = new HashSet<>(); |
| for (IWorkbenchPart part : closingParts) { |
| Saveable[] models = getSaveables(part); |
| if (Arrays.asList(models).contains(model)) { |
| closingPartsWithSameModel.add(part); |
| } |
| } |
| IWorkbenchPartReference[] pagePartRefs = ((WorkbenchPage) page).getSortedParts(); |
| HashSet<IWorkbenchPart> pagePartsWithSameModels = new HashSet<>(); |
| for (IWorkbenchPartReference partRef : pagePartRefs) { |
| IWorkbenchPart part = partRef.getPart(false); |
| if (part != null) { |
| Saveable[] models = getSaveables(part); |
| if (Arrays.asList(models).contains(model)) { |
| pagePartsWithSameModels.add(part); |
| } |
| } |
| } |
| for (IWorkbenchPart part : closingPartsWithSameModel) { |
| pagePartsWithSameModels.remove(part); |
| } |
| return pagePartsWithSameModels.isEmpty(); |
| } |
| |
| /** |
| * Saves the contents of the provided saveable and returns whether the |
| * operation succeeded or not. |
| * |
| * @param saveable |
| * the saveable part to save |
| * @param part |
| * @param confirm |
| * whether the user should be prompted for confirmation of the |
| * save request |
| * @param closing |
| * whether the part will be closed after the save operation has |
| * completed, this may determine whether whether the save |
| * operation will actually be invoked or not |
| * @return <code>true</code> if the saveable's contents has been persisted, |
| * <code>false</code> otherwise |
| * @see ISaveablePart#isSaveOnCloseNeeded() |
| */ |
| public boolean saveSaveable(ISaveablePart saveable, IWorkbenchPart part, boolean confirm, |
| boolean closing) { |
| if (closing && !saveable.isSaveOnCloseNeeded()) { |
| return true; |
| } |
| return SaveableHelper.savePart(saveable, part, legacyWindow, confirm); |
| } |
| |
| /** |
| * Saves an editors in the workbench. If <code>confirm</code> is <code>true</code> |
| * the user is prompted to confirm the command. |
| * |
| * @param confirm |
| * if user confirmation should be sought |
| * @return <code>true</code> if the command succeeded, or <code>false</code> |
| * if the user cancels the command |
| */ |
| @Override |
| public boolean saveEditor(IEditorPart editor, boolean confirm) { |
| return saveSaveable(editor, editor, confirm, false); |
| } |
| |
| @Override |
| public void savePerspective() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void savePerspectiveAs(IPerspectiveDescriptor perspective) { |
| MPerspective visiblePerspective = getPerspectiveStack().getSelectedElement(); |
| // get the original perspective |
| String originalPerspectiveId = visiblePerspective.getElementId(); |
| IPerspectiveDescriptor originalPerspective = getWorkbenchWindow().getWorkbench() |
| .getPerspectiveRegistry().findPerspectiveWithId(originalPerspectiveId); |
| // remove it from our collection of previously opened perspectives |
| sortedPerspectives.remove(originalPerspective); |
| // append the saved perspective |
| sortedPerspectives.add(perspective); |
| |
| visiblePerspective.setLabel(perspective.getLabel()); |
| visiblePerspective.setTooltip(perspective.getLabel()); |
| visiblePerspective.setElementId(perspective.getId()); |
| modelService.cloneElement(visiblePerspective, application); |
| if (perspective instanceof PerspectiveDescriptor) { |
| ((PerspectiveDescriptor) perspective).setHasCustomDefinition(true); |
| } |
| |
| UIEvents.publishEvent(UIEvents.UILifeCycle.PERSPECTIVE_SAVED, visiblePerspective); |
| } |
| |
| @Override |
| public void setEditorAreaVisible(boolean showEditorArea) { |
| MUIElement find = findSharedArea(); |
| if (find != null) { |
| if (showEditorArea) { |
| // make sure it's been rendered if it hasn't been |
| find.setToBeRendered(true); |
| } |
| |
| // If the EA is minimized, restore it... |
| if (showEditorArea) { |
| find.getTags().remove(IPresentationEngine.MINIMIZED); |
| } |
| |
| find.setVisible(showEditorArea); |
| } |
| } |
| |
| private HashMap<MPerspective, Perspective> modelToPerspectiveMapping = new HashMap<>(); |
| |
| private Perspective getPerspective(MPerspective mperspective) { |
| if (mperspective == null) { |
| return null; |
| } |
| if (!modelToPerspectiveMapping.containsKey(mperspective)) { |
| boolean fixedPerspective = false; |
| PerspectiveDescriptor perspectiveDesc = (PerspectiveDescriptor) getPerspectiveDesc(mperspective.getElementId()); |
| if (perspectiveDesc == null) { |
| fixedPerspective = true; |
| perspectiveDesc = fixOrphanPerspective(mperspective); |
| } |
| Perspective p = new Perspective(perspectiveDesc, mperspective, this); |
| modelToPerspectiveMapping.put(mperspective, p); |
| p.initActionSets(); |
| if (fixedPerspective) { |
| UIEvents.publishEvent(UIEvents.UILifeCycle.PERSPECTIVE_SAVED, mperspective); |
| } |
| } |
| return modelToPerspectiveMapping.get(mperspective); |
| } |
| |
| /** |
| * An 'orphan' perspective is one that was originally created through a |
| * contribution but whose contributing bundle is no longer available. In |
| * order to allow it to behave correctly within the environment (for Close, |
| * Reset...) we turn it into a 'custom' perspective on its first activation. |
| * |
| * @return |
| */ |
| private PerspectiveDescriptor fixOrphanPerspective(MPerspective mperspective) { |
| PerspectiveRegistry reg = (PerspectiveRegistry) PlatformUI.getWorkbench().getPerspectiveRegistry(); |
| String perspId = mperspective.getElementId(); |
| String label = mperspective.getLabel(); |
| 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$ |
| IStatus status = StatusUtil.newStatus(IStatus.WARNING, msg, null); |
| StatusManager.getManager().handle(status, StatusManager.LOG); |
| |
| String newDescId = NLS.bind(WorkbenchMessages.Perspective_localCopyLabel, label); |
| while (reg.findPerspectiveWithId(newDescId) != null) { |
| newDescId = NLS.bind(WorkbenchMessages.Perspective_localCopyLabel, newDescId); |
| } |
| PerspectiveDescriptor pd = new PerspectiveDescriptor(perspId, label, null); |
| PerspectiveDescriptor newDesc = reg.createPerspective(newDescId, pd); |
| if (mperspective.getIconURI() != null) { |
| try { |
| ImageDescriptor img = ImageDescriptor.createFromURL(new URI(mperspective.getIconURI()).toURL()); |
| newDesc.setImageDescriptor(img); |
| } catch (MalformedURLException | URISyntaxException e) { |
| WorkbenchPlugin.log(MessageFormat.format("Error on applying configured perspective icon: {0}", //$NON-NLS-1$ |
| mperspective.getIconURI(), e)); |
| } |
| } |
| |
| mperspective.setElementId(newDesc.getId()); |
| mperspective.setLabel(newDesc.getLabel()); |
| sortedPerspectives.add(newDesc); |
| modelService.cloneElement(mperspective, application); |
| newDesc.setHasCustomDefinition(true); |
| return newDesc; |
| } |
| |
| @Override |
| public void setPerspective(IPerspectiveDescriptor perspective) { |
| if (perspective == null) { |
| return; |
| } |
| |
| IPerspectiveDescriptor lastPerspective = getPerspective(); |
| if (lastPerspective != null && lastPerspective.getId().equals(perspective.getId())) { |
| // no change |
| MPerspectiveStack perspectives = getPerspectiveStack(); |
| for (MPerspective mperspective : perspectives.getChildren()) { |
| if (mperspective.getElementId().equals(perspective.getId())) { |
| handleNullRefPlaceHolders(mperspective, window); |
| } |
| } |
| return; |
| } |
| |
| MPerspectiveStack perspectives = getPerspectiveStack(); |
| for (MPerspective mperspective : perspectives.getChildren()) { |
| if (mperspective.getElementId().equals(perspective.getId())) { |
| if (lastPerspective != null) { |
| legacyWindow.firePerspectiveDeactivated(this, lastPerspective); |
| } |
| |
| // this perspective already exists, switch to this one |
| perspectives.setSelectedElement(mperspective); |
| mperspective.getContext().activate(); |
| handleNullRefPlaceHolders(mperspective, window); |
| return; |
| } |
| } |
| |
| MPerspective modelPerspective = (MPerspective) modelService.cloneSnippet(application, |
| perspective.getId(), window); |
| |
| if (modelPerspective == null) { |
| // couldn't find the perspective, create a new one |
| modelPerspective = createPerspective(perspective); |
| } |
| |
| handleNullRefPlaceHolders(modelPerspective, window); |
| |
| modelPerspective.setLabel(perspective.getLabel()); |
| |
| ImageDescriptor imageDescriptor = perspective.getImageDescriptor(); |
| if (imageDescriptor != null) { |
| String imageURL = MenuHelper.getImageUrl(imageDescriptor); |
| modelPerspective.setIconURI(imageURL); |
| } |
| |
| if (lastPerspective != null) { |
| legacyWindow.firePerspectiveDeactivated(this, lastPerspective); |
| } |
| |
| // Hide placeholders for parts that exist in the 'global' areas |
| modelService.hideLocalPlaceholders(window, modelPerspective); |
| |
| // add it to the stack |
| perspectives.getChildren().add(modelPerspective); |
| // activate it |
| perspectives.setSelectedElement(modelPerspective); |
| |
| modelPerspective.getContext().activate(); |
| modelPerspective.getContext().set(ISelectionService.class, selectionService); |
| |
| legacyWindow.firePerspectiveOpened(this, perspective); |
| UIEvents.publishEvent(UIEvents.UILifeCycle.PERSPECTIVE_OPENED, modelPerspective); |
| } |
| |
| private void handleNullRefPlaceHolders(MUIElement element, MWindow refWin) { |
| List<MPlaceholder> nullRefList = ((ModelServiceImpl) modelService).getNullRefPlaceHolders(element, refWin); |
| |
| List<MPart> partList = modelService.findElements(element, null, MPart.class, null); |
| for (MPart part : partList) { |
| if (CompatibilityPart.COMPATIBILITY_VIEW_URI.equals(part.getContributionURI()) |
| && part.getIconURI() == null) { |
| part.getTransientData().put(IPresentationEngine.OVERRIDE_ICON_IMAGE_KEY, |
| ImageDescriptor.getMissingImageDescriptor().createImage()); |
| } |
| } |
| |
| if (nullRefList != null && nullRefList.size() > 0) { |
| for (MPlaceholder ph : nullRefList) { |
| replacePlaceholder(ph); |
| } |
| } |
| } |
| |
| private void replacePlaceholder(MPlaceholder ph) { |
| MPart part = modelService.createModelElement(MPart.class); |
| part.setElementId(ph.getElementId()); |
| part.getTransientData().put(IPresentationEngine.OVERRIDE_ICON_IMAGE_KEY, |
| ImageDescriptor.getMissingImageDescriptor().createImage()); |
| String label = (String) ph.getTransientData().get(IWorkbenchConstants.TAG_LABEL); |
| if (label != null) { |
| part.setLabel(label); |
| } else { |
| part.setLabel(getLabel(ph.getElementId())); |
| } |
| part.setContributionURI(CompatibilityPart.COMPATIBILITY_VIEW_URI); |
| part.setCloseable(true); |
| MElementContainer<MUIElement> curParent = ph.getParent(); |
| int curIndex = curParent.getChildren().indexOf(ph); |
| curParent.getChildren().remove(curIndex); |
| curParent.getChildren().add(curIndex, part); |
| if (curParent.getSelectedElement() == ph) { |
| curParent.setSelectedElement(part); |
| } |
| } |
| |
| private String getLabel(String str) { |
| int index = str.lastIndexOf('.'); |
| if (index == -1) |
| return str; |
| return str.substring(index + 1); |
| } |
| |
| /** |
| * @param perspective |
| * @return never null |
| */ |
| private MPerspective createPerspective(IPerspectiveDescriptor perspective) { |
| MPerspective modelPerspective = modelService.createModelElement(MPerspective.class); |
| |
| // tag it with the same id |
| modelPerspective.setElementId(perspective.getId()); |
| |
| // instantiate the perspective |
| IPerspectiveFactory factory = ((PerspectiveDescriptor) perspective).createFactory(); |
| ModeledPageLayout modelLayout = new ModeledPageLayout(window, modelService, |
| partService, modelPerspective, perspective, this, true); |
| factory.createInitialLayout(modelLayout); |
| PerspectiveTagger.tagPerspective(modelPerspective, modelService); |
| PerspectiveExtensionReader reader = new PerspectiveExtensionReader(); |
| reader.extendLayout(getExtensionTracker(), perspective.getId(), modelLayout); |
| return modelPerspective; |
| } |
| |
| void perspectiveActionSetChanged(Perspective perspective, IActionSetDescriptor descriptor, |
| int changeType) { |
| if (perspective == getActivePerspective()) { |
| actionSets.change(descriptor, changeType); |
| } |
| } |
| |
| |
| /** |
| * Retrieves the perspective stack of the window that's containing this |
| * workbench page. |
| * |
| * @return the stack of perspectives of this page's containing window |
| */ |
| private MPerspectiveStack getPerspectiveStack() { |
| if (_perspectiveStack != null) { |
| return _perspectiveStack; |
| } |
| List<MPerspectiveStack> theStack = modelService.findElements(window, null, |
| MPerspectiveStack.class, null); |
| if (theStack.size() > 0) { |
| _perspectiveStack = theStack.get(0); |
| return _perspectiveStack; |
| } |
| |
| for (MWindowElement child : window.getChildren()) { |
| if (child instanceof MPerspectiveStack) { |
| _perspectiveStack = (MPerspectiveStack) child; |
| return _perspectiveStack; |
| } |
| } |
| |
| MPartSashContainer stickySash = modelService.createModelElement(MPartSashContainer.class); |
| stickySash.setHorizontal(true); |
| |
| MPerspectiveStack perspectiveStack = modelService |
| .createModelElement(MPerspectiveStack.class); |
| perspectiveStack.setElementId(IWorkbenchConstants.PERSPECTIVE_STACK_ID); |
| perspectiveStack.setContainerData("7500"); //$NON-NLS-1$ |
| |
| MPartStack stickyFolder = modelService.createModelElement(MPartStack.class); |
| stickyFolder.setContainerData("2500"); //$NON-NLS-1$ |
| stickyFolder.setElementId("stickyFolderRight"); //$NON-NLS-1$ |
| stickyFolder.setToBeRendered(false); |
| |
| IStickyViewDescriptor[] stickyViews = getWorkbenchWindow().getWorkbench().getViewRegistry() |
| .getStickyViews(); |
| for (IStickyViewDescriptor stickyView : stickyViews) { |
| if (stickyView.getLocation() == IPageLayout.RIGHT) { |
| MStackElement viewModel = ModeledPageLayout.createViewModel(application, |
| stickyView.getId(), false, this, partService, true); |
| stickyFolder.getChildren().add(viewModel); |
| } |
| } |
| |
| stickySash.getChildren().add(perspectiveStack); |
| stickySash.getChildren().add(stickyFolder); |
| stickySash.setSelectedElement(perspectiveStack); |
| |
| window.getChildren().add(stickySash); |
| window.setSelectedElement(stickySash); |
| _perspectiveStack = perspectiveStack; |
| return perspectiveStack; |
| } |
| |
| /** |
| * Sets the active working set for the workbench page. Notifies property |
| * change listener about the change. |
| * |
| * @param newWorkingSet |
| * the active working set for the page. May be null. |
| * @since 2.0 |
| * @deprecated individual views should store a working set if needed |
| */ |
| @Deprecated |
| public void setWorkingSet(IWorkingSet newWorkingSet) { |
| IWorkingSet oldWorkingSet = workingSet; |
| |
| workingSet = newWorkingSet; |
| if (oldWorkingSet != newWorkingSet) { |
| firePropertyChange(CHANGE_WORKING_SET_REPLACE, oldWorkingSet, |
| newWorkingSet); |
| } |
| if (newWorkingSet != null) { |
| WorkbenchPlugin.getDefault().getWorkingSetManager() |
| .addPropertyChangeListener(workingSetPropertyChangeListener); |
| } else { |
| WorkbenchPlugin.getDefault().getWorkingSetManager() |
| .removePropertyChangeListener(workingSetPropertyChangeListener); |
| } |
| } |
| |
| /** |
| * @see IWorkbenchPage |
| */ |
| @Override |
| public void showActionSet(String actionSetID) { |
| Perspective persp = getActivePerspective(); |
| if (persp != null) { |
| ActionSetRegistry reg = WorkbenchPlugin.getDefault() |
| .getActionSetRegistry(); |
| |
| IActionSetDescriptor desc = reg.findActionSet(actionSetID); |
| if (desc != null) { |
| List<IActionSetDescriptor> offActionSets = persp.getAlwaysOffActionSets(); |
| for (IActionSetDescriptor off : offActionSets) { |
| if (off.getId().equals(desc.getId())) { |
| return; |
| } |
| } |
| persp.addActionSet(desc); |
| legacyWindow.updateActionSets(); |
| legacyWindow.firePerspectiveChanged(this, getPerspective(), |
| CHANGE_ACTION_SET_SHOW); |
| } |
| } |
| } |
| |
| /** |
| * See IWorkbenchPage. |
| */ |
| @Override |
| public IViewPart showView(String viewID) throws PartInitException { |
| return showView(viewID, null, VIEW_ACTIVATE); |
| } |
| |
| @Override |
| public IViewPart showView(final String viewID, final String secondaryID, final int mode) |
| throws PartInitException { |
| |
| if (secondaryID != null) { |
| if (secondaryID.length() == 0 || secondaryID.indexOf(":") != -1) { //$NON-NLS-1$ |
| throw new IllegalArgumentException( |
| WorkbenchMessages.WorkbenchPage_IllegalSecondaryId); |
| } |
| } |
| if (!certifyMode(mode)) { |
| throw new IllegalArgumentException(WorkbenchMessages.WorkbenchPage_IllegalViewMode); |
| } |
| |
| // Run op in busy cursor. |
| final String compoundId = secondaryID != null ? viewID + ':' + secondaryID : viewID; |
| final Object[] result = new Object[1]; |
| BusyIndicator.showWhile(null, new Runnable() { |
| @Override |
| public void run() { |
| try { |
| result[0] = busyShowView(compoundId, mode); |
| } catch (PartInitException e) { |
| result[0] = e; |
| } |
| } |
| }); |
| if (result[0] instanceof IViewPart) { |
| return (IViewPart) result[0]; |
| } else if (result[0] instanceof PartInitException) { |
| throw (PartInitException) result[0]; |
| } else { |
| throw new PartInitException(WorkbenchMessages.WorkbenchPage_AbnormalWorkbenchCondition); |
| } |
| } |
| |
| /** |
| * @param mode the mode to test |
| * @return whether the mode is recognized |
| * @since 3.0 |
| */ |
| private boolean certifyMode(int mode) { |
| switch (mode) { |
| case VIEW_ACTIVATE: |
| case VIEW_VISIBLE: |
| case VIEW_CREATE: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| public MUIElement getActiveElement(IWorkbenchPartReference ref) { |
| MUIElement element = null; |
| |
| MPerspective curPersp = modelService.getActivePerspective(window); |
| if (curPersp == null) |
| return null; |
| |
| MPlaceholder eaPH = (MPlaceholder) modelService.find(IPageLayout.ID_EDITOR_AREA, curPersp); |
| MPart model = ((WorkbenchPartReference) ref).getModel(); |
| MPlaceholder placeholder = model.getCurSharedRef(); |
| |
| switch (modelService.getElementLocation(placeholder == null ? model : placeholder)) { |
| case EModelService.IN_ACTIVE_PERSPECTIVE: |
| case EModelService.OUTSIDE_PERSPECTIVE: |
| MUIElement parent = placeholder == null ? model.getParent() : placeholder.getParent(); |
| if (parent instanceof MPartStack) { |
| element = parent; |
| } |
| break; |
| case EModelService.IN_SHARED_AREA: |
| element = eaPH; |
| break; |
| } |
| return element; |
| } |
| |
| @Override |
| public void setPartState(IWorkbenchPartReference ref, int iState) { |
| MUIElement element = getActiveElement(ref); |
| String state = null; |
| |
| if (iState == STATE_MINIMIZED) { |
| state = IPresentationEngine.MINIMIZED; |
| } else if (iState == STATE_MAXIMIZED) { |
| state = IPresentationEngine.MAXIMIZED; |
| } |
| setPartState(element, state); |
| } |
| |
| @Override |
| public int getPartState(IWorkbenchPartReference ref) { |
| int state = STATE_RESTORED; |
| MUIElement element = getActiveElement(ref); |
| |
| if (element != null) { |
| if (element.getTags().contains(IPresentationEngine.MINIMIZED)) { |
| state = STATE_MINIMIZED; |
| } else if (element.getTags().contains(IPresentationEngine.MAXIMIZED)) { |
| state = STATE_MAXIMIZED; |
| } |
| } |
| return state; |
| } |
| |
| // if the state is null, then we'll just restore the view |
| private void setPartState(MUIElement element, String state) { |
| if (element != null) { |
| element.getTags().remove(IPresentationEngine.MINIMIZED_BY_ZOOM); |
| if (IPresentationEngine.MINIMIZED.equals(state)) { |
| element.getTags().remove(IPresentationEngine.MAXIMIZED); |
| element.getTags().add(IPresentationEngine.MINIMIZED); |
| } else if (IPresentationEngine.MAXIMIZED.equals(state)) { |
| element.getTags().remove(IPresentationEngine.MINIMIZED); |
| element.getTags().add(IPresentationEngine.MAXIMIZED); |
| } else { |
| element.getTags().remove(IPresentationEngine.MINIMIZED); |
| element.getTags().remove(IPresentationEngine.MAXIMIZED); |
| } |
| } |
| } |
| |
| /** |
| * updateActionBars method comment. |
| */ |
| public void updateActionBars() { |
| legacyWindow.updateActionBars(); |
| } |
| |
| |
| @Override |
| public void zoomOut() { |
| // TODO compat: what does the zoom do? |
| } |
| |
| @Override |
| public void toggleZoom(IWorkbenchPartReference ref) { |
| MUIElement element = getActiveElement(ref); |
| if (element != null) { |
| String state = null; |
| if (!element.getTags().contains(IPresentationEngine.MAXIMIZED)) { |
| state = IPresentationEngine.MAXIMIZED; |
| } |
| this.setPartState(element, state); |
| } |
| } |
| |
| |
| @Override |
| public IPerspectiveDescriptor[] getOpenPerspectives() { |
| MPerspectiveStack perspectiveStack = modelService.findElements(window, null, |
| MPerspectiveStack.class, null).get(0); |
| IPerspectiveRegistry registry = PlatformUI.getWorkbench().getPerspectiveRegistry(); |
| |
| ArrayList<IPerspectiveDescriptor> tmp = new ArrayList<>( |
| perspectiveStack.getChildren().size()); |
| for (MPerspective persp : perspectiveStack.getChildren()) { |
| String perspectiveId = persp.getElementId(); |
| IPerspectiveDescriptor desc = registry.findPerspectiveWithId(perspectiveId); |
| if (desc != null) { |
| tmp.add(desc); |
| } |
| } |
| IPerspectiveDescriptor[] descs = new IPerspectiveDescriptor[tmp.size()]; |
| tmp.toArray(descs); |
| |
| return descs; |
| } |
| |
| @Override |
| public IPerspectiveDescriptor[] getSortedPerspectives() { |
| return sortedPerspectives.toArray(new IPerspectiveDescriptor[sortedPerspectives.size()]); |
| } |
| |
| |
| |
| /** |
| * Returns the reference to the given part, or <code>null</code> if it has no reference |
| * (i.e. it is not a top-level part in this workbench page). |
| * |
| * @param part the part |
| * @return the part's reference or <code>null</code> if the given part does not belong |
| * to this workbench page |
| */ |
| @Override |
| public IWorkbenchPartReference getReference(IWorkbenchPart part) { |
| if (part != null) { |
| IWorkbenchPartSite site = part.getSite(); |
| if (site instanceof PartSite) { |
| return ((PartSite) site).getPartReference(); |
| } |
| } |
| return null; |
| } |
| |
| public MPerspective getCurrentPerspective() { |
| MPerspectiveStack stack = getPerspectiveStack(); |
| return stack == null ? null : stack.getSelectedElement(); |
| } |
| |
| Perspective getActivePerspective() { |
| return getPerspective(getCurrentPerspective()); |
| } |
| |
| @Override |
| public IViewPart[] getViewStack(IViewPart part) { |
| MPart mpart = partService.findPart(part.getSite().getId()); |
| if (mpart != null) { |
| MElementContainer<?> parent = mpart.getParent(); |
| if (parent == null) { |
| // this is a shared part, check for placeholders |
| MPlaceholder placeholder = mpart.getCurSharedRef(); |
| if (placeholder != null) { |
| parent = placeholder.getParent(); |
| } |
| } |
| |
| if (parent instanceof MPartStack) { |
| MStackElement selectedElement = ((MPartStack) parent).getSelectedElement(); |
| final MUIElement topPart = selectedElement instanceof MPlaceholder ? ((MPlaceholder) selectedElement) |
| .getRef() : null; |
| |
| List<CompatibilityView> stack = new ArrayList<>(); |
| for (Object child : parent.getChildren()) { |
| MPart siblingPart = child instanceof MPart ? (MPart) child |
| : (MPart) ((MPlaceholder) child).getRef(); |
| // Bug 398433 - guard against NPE |
| Object siblingObject = siblingPart != null ? siblingPart.getObject() : null; |
| if (siblingObject instanceof CompatibilityView) { |
| stack.add((CompatibilityView) siblingObject); |
| } |
| } |
| |
| // sort the list by activation order (most recently activated |
| // first) |
| Collections.sort(stack, new Comparator<CompatibilityView>() { |
| @Override |
| public int compare(CompatibilityView o1, CompatibilityView o2) { |
| MPart model1 = o1.getModel(); |
| MPart model2 = o2.getModel(); |
| |
| /* |
| * WORKAROUND: Since we only have the activation list |
| * and not a bingToTop list, we can't set/know the order |
| * for inactive stacks. This workaround makes sure that |
| * the topmost part is at least at the first position. |
| */ |
| if (model1 == topPart) |
| return Integer.MIN_VALUE; |
| if (model2 == topPart) |
| return Integer.MAX_VALUE; |
| |
| int pos1 = activationList.indexOf(model1); |
| int pos2 = activationList.indexOf(model2); |
| if (pos1 == -1) |
| pos1 = Integer.MAX_VALUE; |
| if (pos2 == -1) |
| pos2 = Integer.MAX_VALUE; |
| return pos1 - pos2; |
| } |
| }); |
| |
| IViewPart[] result = new IViewPart[stack.size()]; |
| for (int i = 0; i < result.length; i++) { |
| result[i] = stack.get(i).getView(); |
| } |
| return result; |
| } |
| |
| // not in a stack, standalone |
| return new IViewPart[] { part }; |
| } |
| return null; |
| } |
| |
| |
| @Override |
| public IExtensionTracker getExtensionTracker() { |
| if (tracker == null) { |
| tracker = new UIExtensionTracker(getWorkbenchWindow().getWorkbench().getDisplay()); |
| } |
| return tracker; |
| } |
| |
| private final static String[] EMPTY_STRING_ARRAY = new String[0]; |
| |
| private String[] getArrayForTag(String tagPrefix) { |
| List<String> id = getCollectionForTag(tagPrefix); |
| if (id == null) |
| return EMPTY_STRING_ARRAY; |
| return id.toArray(new String[id.size()]); |
| } |
| |
| private List<String> getCollectionForTag(String tagPrefix) { |
| MPerspective perspective = getPerspectiveStack().getSelectedElement(); |
| if (perspective == null) { |
| return Collections.emptyList(); |
| } |
| return ModeledPageLayout.getIds(perspective, tagPrefix); |
| } |
| |
| @Override |
| public String[] getNewWizardShortcuts() { |
| return getArrayForTag(ModeledPageLayout.NEW_WIZARD_TAG); |
| } |
| |
| @Override |
| public String[] getPerspectiveShortcuts() { |
| return getArrayForTag(ModeledPageLayout.PERSP_SHORTCUT_TAG); |
| } |
| |
| @Override |
| public String[] getShowViewShortcuts() { |
| return getArrayForTag(ModeledPageLayout.SHOW_VIEW_TAG); |
| } |
| |
| |
| |
| public boolean isPartVisible(IWorkbenchPartReference reference) { |
| IWorkbenchPart part = reference.getPart(false); |
| // Can't be visible if it isn't created yet |
| if (part == null) { |
| return false; |
| } |
| |
| return isPartVisible(part); |
| } |
| |
| @Override |
| public IWorkingSet[] getWorkingSets() { |
| return workingSets; |
| } |
| |
| @Override |
| public void setWorkingSets(IWorkingSet[] newWorkingSets) { |
| if (newWorkingSets != null) { |
| WorkbenchPlugin |
| .getDefault() |
| .getWorkingSetManager() |
| .addPropertyChangeListener(workingSetPropertyChangeListener); |
| } else { |
| WorkbenchPlugin.getDefault().getWorkingSetManager() |
| .removePropertyChangeListener( |
| workingSetPropertyChangeListener); |
| } |
| |
| if (newWorkingSets == null) { |
| newWorkingSets = new IWorkingSet[0]; |
| } |
| |
| IWorkingSet[] oldWorkingSets = workingSets; |
| |
| // filter out any duplicates if necessary |
| if (newWorkingSets.length > 1) { |
| Set<IWorkingSet> setOfSets = new HashSet<>(); |
| for (IWorkingSet workingSet : newWorkingSets) { |
| if (workingSet == null) { |
| throw new IllegalArgumentException(); |
| } |
| setOfSets.add(workingSet); |
| } |
| newWorkingSets = setOfSets.toArray(new IWorkingSet[setOfSets.size()]); |
| } |
| |
| workingSets = newWorkingSets; |
| if (!Arrays.equals(oldWorkingSets, newWorkingSets)) { |
| firePropertyChange(CHANGE_WORKING_SETS_REPLACE, oldWorkingSets, |
| newWorkingSets); |
| if (aggregateWorkingSet != null) { |
| aggregateWorkingSet.setComponents(workingSets); |
| } |
| } |
| } |
| |
| @Override |
| public IWorkingSet getAggregateWorkingSet() { |
| if (aggregateWorkingSet == null) { |
| IWorkingSetManager workingSetManager = PlatformUI.getWorkbench() |
| .getWorkingSetManager(); |
| |
| if (aggregateWorkingSetId == null) { |
| aggregateWorkingSetId = generateAggregateWorkingSetId(); |
| } else { |
| aggregateWorkingSet = (AggregateWorkingSet) workingSetManager.getWorkingSet(aggregateWorkingSetId); |
| } |
| if (aggregateWorkingSet == null) { |
| aggregateWorkingSet = (AggregateWorkingSet) workingSetManager |
| .createAggregateWorkingSet(aggregateWorkingSetId, |
| WorkbenchMessages.WorkbenchPage_workingSet_default_label, |
| getWorkingSets()); |
| workingSetManager.addWorkingSet(aggregateWorkingSet); |
| } |
| } |
| return aggregateWorkingSet; |
| } |
| |
| private String generateAggregateWorkingSetId() { |
| return "Aggregate for window " + System.currentTimeMillis(); //$NON-NLS-1$ |
| } |
| |
| @Override |
| public void showEditor(IEditorReference ref) { |
| // FIXME compat showEditor |
| E4Util.unsupported("showEditor"); //$NON-NLS-1$ |
| |
| } |
| |
| @Override |
| public void hideEditor(IEditorReference ref) { |
| // FIXME compat hideEditor |
| E4Util.unsupported("hideEditor"); //$NON-NLS-1$ |
| |
| } |
| |
| private String getEditorImageURI(EditorReference reference) { |
| String iconURI = null; |
| |
| EditorDescriptor descriptor = reference.getDescriptor(); |
| if (descriptor != null) { |
| IConfigurationElement element = descriptor.getConfigurationElement(); |
| if (element != null) { |
| iconURI = MenuHelper.getIconURI(element, IWorkbenchRegistryConstants.ATT_ICON); |
| } |
| } |
| return iconURI; |
| } |
| |
| @Override |
| public IMemento[] getEditorState(IEditorReference[] editorRefs, boolean includeInputState) { |
| IMemento[] m = new IMemento[editorRefs.length]; |
| for (int i = 0; i < editorRefs.length; i++) { |
| m[i] = ((EditorReference) editorRefs[i]).getEditorState(); |
| if (!includeInputState && m[i] != null) { |
| m[i] = m[i].getChild(IWorkbenchConstants.TAG_EDITOR_STATE); |
| } |
| } |
| return m; |
| } |
| |
| @Override |
| public IEditorReference[] openEditors(IEditorInput[] inputs, String[] editorIDs, int matchFlags) throws MultiPartInitException { |
| return openEditors(inputs, editorIDs, null, matchFlags, 0); |
| } |
| |
| @Override |
| public IEditorReference[] openEditors(IEditorInput[] inputs, String[] editorIDs, |
| IMemento[] mementos, int matchFlags, int activationIndex) |
| throws MultiPartInitException { |
| // If we are only working with mementos create a placeholder array of |
| // nulls |
| if (inputs == null) { |
| Assert.isTrue(mementos != null); |
| inputs = new IEditorInput[mementos.length]; |
| } |
| |
| // If we are only working with mementos create a placeholder array of |
| // nulls |
| if (editorIDs == null) { |
| Assert.isTrue(mementos != null); |
| editorIDs = new String[mementos.length]; |
| } |
| |
| Assert.isTrue(inputs.length == editorIDs.length); |
| Assert.isTrue(inputs.length > 0); |
| Assert.isTrue(mementos == null || mementos.length == inputs.length); |
| |
| PartInitException[] exceptions = new PartInitException[inputs.length]; |
| IEditorReference[] references = new IEditorReference[inputs.length]; |
| boolean hasFailures = false; |
| |
| IEditorRegistry reg = getWorkbenchWindow().getWorkbench().getEditorRegistry(); |
| MPart editorToActivate = null; |
| for (int i = 0; i < inputs.length; i++) { |
| String curEditorID = editorIDs == null ? null : editorIDs[i]; |
| IEditorInput curInput = inputs == null ? null : inputs[i]; |
| IMemento curMemento = mementos == null ? null : mementos[i]; |
| |
| // If we don't have an editorID get it from the memento |
| if (curEditorID == null && curMemento != null) { |
| curEditorID = curMemento.getString(IWorkbenchConstants.TAG_ID); |
| } |
| |
| // If we don't have an input create on from the memento |
| if (curInput == null && curMemento != null) { |
| try { |
| curInput = EditorReference.createInput(curMemento); |
| } catch (PartInitException e) { |
| curInput = null; |
| exceptions[i] = e; |
| hasFailures = true; |
| continue; |
| } |
| } |
| |
| // Adjust the memento so that it's always 'comlpete (i.e. including |
| // both input and editor state) |
| if (curMemento != null && !curMemento.getID().equals(IWorkbenchConstants.TAG_EDITOR)) { |
| XMLMemento outerMem = XMLMemento.createWriteRoot(IWorkbenchConstants.TAG_EDITOR); |
| outerMem.putString(IWorkbenchConstants.TAG_ID, curEditorID); |
| outerMem.copyChild(curMemento); |
| |
| XMLMemento inputMem = (XMLMemento) outerMem |
| .createChild(IWorkbenchConstants.TAG_INPUT); |
| inputMem.putString(IWorkbenchConstants.TAG_FACTORY_ID, curInput.getPersistable() |
| .getFactoryId()); |
| inputMem.putString(IWorkbenchConstants.TAG_PATH, curInput.getName()); |
| } |
| |
| // OK, by this point we should have the EditorInput, the editor ID |
| // and the memento (if any) |
| if (reg.findEditor(curEditorID) == null) { |
| references[i] = null; |
| exceptions[i] = new PartInitException(NLS.bind( |
| WorkbenchMessages.EditorManager_unknownEditorIDMessage, curEditorID)); |
| hasFailures = true; |
| } else if (curInput == null) { |
| references[i] = null; |
| exceptions[i] = new PartInitException(NLS.bind( |
| WorkbenchMessages.EditorManager_no_persisted_state, curEditorID)); |
| hasFailures = true; |
| } else { |
| // Is there an existing editor ? |
| IEditorReference[] existingEditors = findEditors(curInput, curEditorID, |
| matchFlags); |
| if (existingEditors.length == 0) { |
| MPart editor = partService.createPart(CompatibilityEditor.MODEL_ELEMENT_ID); |
| references[i] = createEditorReferenceForPart(editor, curInput, curEditorID, |
| null); |
| |
| if (i == activationIndex) |
| editorToActivate = editor; |
| |
| // Set the information in the supplied IMemento into the |
| // editor's model |
| if (curMemento instanceof XMLMemento) { |
| XMLMemento memento = (XMLMemento) curMemento; |
| StringWriter writer = new StringWriter(); |
| try { |
| memento.save(writer); |
| editor.getPersistedState().put(WorkbenchPartReference.MEMENTO_KEY, |
| writer.toString()); |
| } catch (IOException e) { |
| WorkbenchPlugin.log(e); |
| } |
| } |
| |
| editor.setLabel(references[i].getTitle()); |
| editor.setTooltip(references[i].getTitleToolTip()); |
| editor.setIconURI(getEditorImageURI((EditorReference) references[i])); |
| ((PartServiceImpl) partService).addPart(editor); |
| } else { |
| // Use the existing editor, update the state if it has *not* |
| // been rendered |
| EditorReference ee = (EditorReference) existingEditors[0]; |
| if (i == activationIndex) |
| editorToActivate = ee.getModel(); |
| |
| if (ee.getModel().getWidget() == null) { |
| // Set the information in the supplied IMemento into the |
| // editor's model |
| if (curMemento instanceof XMLMemento) { |
| XMLMemento momento = (XMLMemento) curMemento; |
| StringWriter writer = new StringWriter(); |
| try { |
| momento.save(writer); |
| ee.getModel().getPersistedState() |
| .put(WorkbenchPartReference.MEMENTO_KEY, writer.toString()); |
| } catch (IOException e) { |
| WorkbenchPlugin.log(e); |
| } |
| } |
| } else { |
| // editor already rendered, try to update its state |
| if (curMemento != null |
| && ee.getModel().getObject() instanceof CompatibilityEditor) { |
| CompatibilityEditor ce = (CompatibilityEditor) ee.getModel() |
| .getObject(); |
| if (ce.getEditor() instanceof IPersistableEditor) { |
| IPersistableEditor pe = (IPersistableEditor) ce.getEditor(); |
| |
| // Extract the 'editorState' from the memento |
| IMemento editorMem = curMemento |
| .getChild(IWorkbenchConstants.TAG_EDITOR_STATE); |
| if (editorMem == null) { |
| // Must be an externally defined memento, |
| // take the second child |
| IMemento[] kids = curMemento.getChildren(); |
| if (kids.length == 2) |
| editorMem = kids[1]; |
| } |
| if (editorMem != null) |
| pe.restoreState(editorMem); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| if (editorToActivate != null) { |
| partService.activate(editorToActivate); |
| } |
| |
| boolean hasSuccesses = false; |
| for (IEditorReference reference : references) { |
| if (reference != null) { |
| hasSuccesses = true; |
| legacyWindow.firePerspectiveChanged(this, getPerspective(), reference, |
| CHANGE_EDITOR_OPEN); |
| } |
| } |
| |
| // only fire this event if an editor was opened |
| if (hasSuccesses) { |
| legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_EDITOR_OPEN); |
| } |
| |
| if (hasFailures) { |
| throw new MultiPartInitException(references, exceptions); |
| } |
| |
| return references; |
| } |
| |
| void updatePerspectiveActionSets() { |
| updateActionSets(null, getActivePerspective()); |
| } |
| |
| void fireInitialPartVisibilityEvents() { |
| MPerspective selectedElement = getPerspectiveStack().getSelectedElement(); |
| // technically shouldn't be null here |
| if (selectedElement != null) { |
| Collection<MPart> parts = modelService.findElements(selectedElement, null, MPart.class, |
| null); |
| List<MPart> visibleParts = new ArrayList<>(parts.size()); |
| for (MPart part : parts) { |
| if (isVisible(selectedElement, part)) { |
| visibleParts.add(part); |
| } |
| } |
| |
| for (MPart part : visibleParts) { |
| firePartVisible(part); |
| } |
| } |
| } |
| |
| private boolean isVisible(MPerspective perspective, MUIElement element) { |
| if (element == perspective) { |
| return true; |
| } else if (element.isVisible() && element.isToBeRendered()) { |
| MElementContainer<?> parent = element.getParent(); |
| if (parent instanceof MPartStack) { |
| if (parent.getSelectedElement() == element) { |
| return isVisible(perspective, parent); |
| } |
| } else if (parent == null) { |
| MPlaceholder placeholder = element.getCurSharedRef(); |
| return placeholder == null ? false : isVisible(perspective, placeholder); |
| } else { |
| return isVisible(perspective, parent); |
| } |
| } |
| return false; |
| } |
| |
| private void firePartActivated(MPart part) { |
| |
| Object client = part.getObject(); |
| if (client instanceof CompatibilityPart) { |
| final IWorkbenchPart workbenchPart = ((CompatibilityPart) client).getPart(); |
| final IWorkbenchPartReference partReference = getReference(workbenchPart); |
| if (partReference == null) { |
| WorkbenchPlugin.log("Reference is null in firePartActivated"); //$NON-NLS-1$ |
| return; |
| } |
| |
| for (final IPartListener listener : partListenerList) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partActivated(workbenchPart); |
| } |
| }); |
| } |
| |
| for (final IPartListener2 listener : partListener2List) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partActivated(partReference); |
| } |
| }); |
| } |
| } |
| else if (client != null) { |
| if (part.getTransientData().get(E4PartWrapper.E4_WRAPPER_KEY) instanceof E4PartWrapper) { |
| IWorkbenchPart workbenchPart = (IWorkbenchPart) part.getTransientData() |
| .get(E4PartWrapper.E4_WRAPPER_KEY); |
| final IWorkbenchPartReference partReference = getReference(workbenchPart); |
| |
| if (partReference != null) { |
| for (final IPartListener listener : partListenerList) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partActivated(workbenchPart); |
| } |
| }); |
| } |
| |
| for (final IPartListener2 listener : partListener2List) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partActivated(partReference); |
| } |
| }); |
| } |
| } |
| } |
| } |
| } |
| |
| private void firePartDeactivated(MPart part) { |
| Object client = part.getObject(); |
| if (client instanceof CompatibilityPart) { |
| final IWorkbenchPart workbenchPart = ((CompatibilityPart) client).getPart(); |
| final IWorkbenchPartReference partReference = getReference(workbenchPart); |
| |
| for (final IPartListener listener : partListenerList) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partDeactivated(workbenchPart); |
| } |
| }); |
| } |
| |
| for (final IPartListener2 listener : partListener2List) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partDeactivated(partReference); |
| } |
| }); |
| } |
| } else if (client != null) { |
| if (part.getTransientData().get(E4PartWrapper.E4_WRAPPER_KEY) instanceof E4PartWrapper) { |
| IWorkbenchPart workbenchPart = (IWorkbenchPart) part.getTransientData() |
| .get(E4PartWrapper.E4_WRAPPER_KEY); |
| final IWorkbenchPartReference partReference = getReference(workbenchPart); |
| |
| if (partReference != null) { |
| for (final IPartListener listener : partListenerList) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partDeactivated(workbenchPart); |
| } |
| }); |
| } |
| |
| for (final IPartListener2 listener : partListener2List) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partDeactivated(partReference); |
| } |
| }); |
| } |
| } |
| } |
| } |
| } |
| |
| public void firePartOpened(CompatibilityPart compatibilityPart) { |
| final IWorkbenchPart part = compatibilityPart.getPart(); |
| final IWorkbenchPartReference partReference = compatibilityPart.getReference(); |
| |
| SaveablesList saveablesList = (SaveablesList) getWorkbenchWindow().getService( |
| ISaveablesLifecycleListener.class); |
| saveablesList.postOpen(part); |
| |
| for (final IPartListener listener : partListenerList) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partOpened(part); |
| } |
| }); |
| } |
| |
| for (final IPartListener2 listener : partListener2List) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partOpened(partReference); |
| } |
| }); |
| } |
| |
| if (part instanceof IPageChangeProvider) { |
| ((IPageChangeProvider) part).addPageChangedListener(pageChangedListener); |
| } |
| |
| if (compatibilityPart instanceof CompatibilityView) { |
| legacyWindow.firePerspectiveChanged(this, getPerspective(), partReference, |
| CHANGE_VIEW_SHOW); |
| legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_VIEW_SHOW); |
| } |
| } |
| |
| public void firePartClosed(CompatibilityPart compatibilityPart) { |
| final IWorkbenchPart part = compatibilityPart.getPart(); |
| final WorkbenchPartReference partReference = compatibilityPart.getReference(); |
| MPart model = partReference.getModel(); |
| |
| SaveablesList modelManager = (SaveablesList) getWorkbenchWindow().getService( |
| ISaveablesLifecycleListener.class); |
| Object postCloseInfo = modelManager.preCloseParts(Collections.singletonList(part), false, |
| getWorkbenchWindow()); |
| if (postCloseInfo != null) { |
| modelManager.postClose(postCloseInfo); |
| } |
| |
| for (final IPartListener listener : partListenerList) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partClosed(part); |
| } |
| }); |
| } |
| |
| for (final IPartListener2 listener : partListener2List) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partClosed(partReference); |
| } |
| }); |
| } |
| |
| if (part instanceof IViewPart) { |
| viewReferences.remove(partReference); |
| } else { |
| editorReferences.remove(partReference); |
| } |
| |
| for (int i = 0; i < activationList.size(); i++) { |
| if (model == activationList.get(i)) { |
| activationList.remove(i); |
| break; |
| } |
| } |
| |
| MPart activePart = partService.getActivePart(); |
| if (activePart == null) { |
| // unset active part/editor sources if no active part found |
| updateActivePartSources(null); |
| updateActiveEditorSources(null); |
| } else if (part instanceof IEditorPart) { |
| // an editor got closed, update information about active editor |
| IEditorPart activeEditor = getActiveEditor(); |
| if (activeEditor == null) { |
| updateActiveEditorSources(activePart); |
| } else { |
| updateActiveEditorSources(findPart(activeEditor)); |
| } |
| } |
| |
| if (part instanceof IPageChangeProvider) { |
| ((IPageChangeProvider) part).removePageChangedListener(pageChangedListener); |
| } |
| |
| if (compatibilityPart instanceof CompatibilityView) { |
| legacyWindow.firePerspectiveChanged(this, getPerspective(), partReference, |
| CHANGE_VIEW_HIDE); |
| legacyWindow.firePerspectiveChanged(this, getPerspective(), CHANGE_VIEW_HIDE); |
| } |
| } |
| |
| private void firePartBroughtToTop(MPart part) { |
| Object client = part.getObject(); |
| if (client instanceof CompatibilityPart) { |
| final IWorkbenchPart workbenchPart = ((CompatibilityPart) client).getPart(); |
| final IWorkbenchPartReference partReference = getReference(workbenchPart); |
| |
| for (final IPartListener listener : partListenerList) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partBroughtToTop(workbenchPart); |
| } |
| }); |
| } |
| |
| for (final IPartListener2 listener : partListener2List) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partBroughtToTop(partReference); |
| } |
| }); |
| } |
| } else { |
| Integer val = partEvents.get(part); |
| if (val == null) { |
| partEvents.put(part, Integer.valueOf(FIRE_PART_BROUGHTTOTOP)); |
| } else { |
| partEvents.put(part, Integer.valueOf(val.intValue() | FIRE_PART_BROUGHTTOTOP)); |
| } |
| } |
| } |
| |
| private WeakHashMap<MPart, Integer> partEvents = new WeakHashMap<>(); |
| private static final int FIRE_PART_VISIBLE = 0x1; |
| private static final int FIRE_PART_BROUGHTTOTOP = 0x2; |
| |
| private EventHandler firingHandler = new EventHandler() { |
| @Override |
| public void handleEvent(Event event) { |
| Object element = event.getProperty(UIEvents.EventTags.ELEMENT); |
| Object value = event.getProperty(UIEvents.EventTags.NEW_VALUE); |
| if (value instanceof CompatibilityPart && element instanceof MPart) { |
| Integer events = partEvents.remove(element); |
| if (events != null) { |
| int e = events.intValue(); |
| if ((e & FIRE_PART_VISIBLE) == FIRE_PART_VISIBLE) { |
| firePartVisible((MPart) element); |
| } |
| if ((e & FIRE_PART_BROUGHTTOTOP) == FIRE_PART_BROUGHTTOTOP) { |
| firePartBroughtToTop((MPart) element); |
| } |
| } |
| } |
| } |
| }; |
| |
| private EventHandler childrenHandler = new EventHandler() { |
| @Override |
| public void handleEvent(Event event) { |
| Object changedObj = event.getProperty(UIEvents.EventTags.ELEMENT); |
| |
| // ...in this window ? |
| MUIElement changedElement = (MUIElement) changedObj; |
| if (modelService.getTopLevelWindowFor(changedElement) != window) |
| return; |
| |
| if (UIEvents.isADD(event)) { |
| for (Object o : UIEvents.asIterable(event, UIEvents.EventTags.NEW_VALUE)) { |
| if (!(o instanceof MUIElement)) |
| continue; |
| |
| // We have to iterate through the new elements to see if any |
| // contain (or are) MParts (e.g. we may have dragged a split |
| // editor which contains two editors, both with EditorRefs) |
| MUIElement element = (MUIElement) o; |
| List<MPart> addedParts = modelService.findElements(element, null, MPart.class, |
| null); |
| for (MPart part : addedParts) { |
| IWorkbenchPartReference ref = (IWorkbenchPartReference) part |
| .getTransientData().get( |
| IWorkbenchPartReference.class.getName()); |
| |
| // For now we only check for editors changing pages |
| if (ref instanceof EditorReference && getEditorReference(part) == null) { |
| addEditorReference((EditorReference) ref); |
| } |
| } |
| } |
| } |
| } |
| }; |
| |
| // FIXME: convert me to e4 events! |
| private void firePartVisible(MPart part) { |
| Object client = part.getObject(); |
| if (client instanceof CompatibilityPart) { |
| IWorkbenchPart workbenchPart = ((CompatibilityPart) client).getPart(); |
| final IWorkbenchPartReference partReference = getReference(workbenchPart); |
| |
| for (final IPartListener2 listener : partListener2List) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partVisible(partReference); |
| } |
| }); |
| } |
| } else { |
| Integer val = partEvents.get(part); |
| if (val == null) { |
| partEvents.put(part, Integer.valueOf(FIRE_PART_VISIBLE)); |
| } else { |
| partEvents.put(part, Integer.valueOf(val.intValue() | FIRE_PART_VISIBLE)); |
| } |
| } |
| } |
| |
| // FIXME: convert me to e4 events! |
| public void firePartHidden(MPart part) { |
| Object client = part.getObject(); |
| if (client instanceof CompatibilityPart) { |
| IWorkbenchPart workbenchPart = ((CompatibilityPart) client).getPart(); |
| final IWorkbenchPartReference partReference = getReference(workbenchPart); |
| |
| for (final IPartListener2 listener : partListener2List) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partHidden(partReference); |
| } |
| }); |
| } |
| } |
| } |
| |
| public void firePartInputChanged(final IWorkbenchPartReference partReference) { |
| for (final IPartListener2 listener : partListener2List) { |
| SafeRunner.run(new SafeRunnable() { |
| @Override |
| public void run() throws Exception { |
| listener.partInputChanged(partReference); |
| } |
| }); |
| } |
| } |
| |
| @Override |
| public int getEditorReuseThreshold() { |
| IPreferenceStore store = WorkbenchPlugin.getDefault().getPreferenceStore(); |
| return store.getInt(IPreferenceConstants.REUSE_EDITORS); |
| } |
| |
| @Override |
| public void setEditorReuseThreshold(int openEditors) { |
| // this is an empty implementation in 3.x, see IPageLayout's |
| // setEditorReuseThreshold |
| } |
| |
| /** |
| * Opens an editor represented by the descriptor with the given input. |
| * |
| * @param fileEditorInput |
| * the input that the editor should open |
| * @param editorDescriptor |
| * the descriptor of the editor to open |
| * @param activate |
| * <tt>true</tt> if the editor should be activated, |
| * <tt>false</tt> otherwise |
| * @param editorState |
| * the previously saved state of the editor as a memento, this |
| * may be <tt>null</tt> |
| * @return the opened editor |
| * @exception PartInitException |
| * if the editor could not be created or initialized |
| */ |
| public IEditorPart openEditorFromDescriptor(IEditorInput fileEditorInput, |
| IEditorDescriptor editorDescriptor, final boolean activate, final IMemento editorState) |
| throws PartInitException { |
| if (editorDescriptor.isOpenExternal()) { |
| openExternalEditor((EditorDescriptor) editorDescriptor, fileEditorInput); |
| return null; |
| } |
| return openEditor(fileEditorInput, editorDescriptor.getId(), activate, MATCH_INPUT, |
| editorState, true); |
| } |
| |
| /** |
| * Open a specific external editor on an file based on the descriptor. |
| */ |
| private IEditorReference openExternalEditor(final EditorDescriptor desc, IEditorInput input) |
| throws PartInitException { |
| final CoreException ex[] = new CoreException[1]; |
| |
| final IPathEditorInput pathInput = getPathEditorInput(input); |
| if (pathInput != null && pathInput.getPath() != null) { |
| BusyIndicator.showWhile(legacyWindow.getWorkbench().getDisplay(), new Runnable() { |
| @Override |
| public void run() { |
| try { |
| if (desc.getLauncher() != null) { |
| // open using launcher |
| Object launcher = WorkbenchPlugin.createExtension(desc |
| .getConfigurationElement(), |
| IWorkbenchRegistryConstants.ATT_LAUNCHER); |
| ((IEditorLauncher) launcher).open(pathInput.getPath()); |
| } else { |
| // open using command |
| ExternalEditor oEditor = new ExternalEditor(pathInput.getPath(), desc); |
| oEditor.open(); |
| } |
| } catch (CoreException e) { |
| ex[0] = e; |
| } |
| } |
| }); |
| } else { |
| throw new PartInitException(NLS.bind( |
| WorkbenchMessages.EditorManager_errorOpeningExternalEditor, desc.getFileName(), |
| desc.getId())); |
| } |
| |
| if (ex[0] != null) { |
| throw new PartInitException(NLS.bind( |
| WorkbenchMessages.EditorManager_errorOpeningExternalEditor, desc.getFileName(), |
| desc.getId()), ex[0]); |
| } |
| |
| recordEditor(input, desc); |
| // we do not have an editor part for external editors |
| return null; |
| } |
| |
| private IPathEditorInput getPathEditorInput(IEditorInput input) { |
| if (input instanceof IPathEditorInput) |
| return (IPathEditorInput) input; |
| return Adapters.adapt(input, IPathEditorInput.class); |
| } |
| |
| /** |
| * Unzooms the shared area if there are no more rendered parts contained |
| * within it. |
| * |
| * @see #unzoomSharedArea(MUIElement) |
| */ |
| private void unzoomSharedArea() { |
| MPerspective curPersp = getPerspectiveStack().getSelectedElement(); |
| if (curPersp == null) |
| return; |
| |
| MPlaceholder eaPH = (MPlaceholder) modelService.find(IPageLayout.ID_EDITOR_AREA, curPersp); |
| for (MPart part : modelService.findElements(eaPH, null, MPart.class, null)) { |
| if (part.isToBeRendered()) { |
| MPlaceholder placeholder = part.getCurSharedRef(); |
| if (placeholder == null || placeholder.isToBeRendered()) { |
| return; |
| } |
| } |
| } |
| |
| setPartState(eaPH, null); |
| } |
| |
| /** |
| * Unzooms the shared area if the specified element is in the shared area. |
| * |
| * @param element |
| * the element to check if it is in the shared area |
| * @see #unzoomSharedArea() |
| */ |
| private void unzoomSharedArea(MUIElement element) { |
| if (modelService.getElementLocation(element) == EModelService.IN_SHARED_AREA) { |
| unzoomSharedArea(); |
| } |
| } |
| |
| /** |
| * An event handler for listening to parts and placeholders being |
| * unrendered. |
| */ |
| private EventHandler referenceRemovalEventHandler = new EventHandler() { |
| @Override |
| public void handleEvent(Event event) { |
| if (Boolean.TRUE.equals(event.getProperty(UIEvents.EventTags.NEW_VALUE))) { |
| return; |
| } |
| |
| Object element = event.getProperty(UIEvents.EventTags.ELEMENT); |
| if (element instanceof MPlaceholder) { |
| MUIElement ref = ((MPlaceholder) element).getRef(); |
| // a placeholder has been unrendered, check to see if the shared |
| // area needs to be unzoomed |
| unzoomSharedArea(ref); |
| |
| if (ref instanceof MPart) { |
| // find all placeholders for this part |
| List<MPlaceholder> placeholders = modelService.findElements(window, |
| ref.getElementId(), MPlaceholder.class, null, |
| EModelService.IN_ANY_PERSPECTIVE | EModelService.IN_SHARED_AREA |
| | EModelService.OUTSIDE_PERSPECTIVE); |
| for (MPlaceholder placeholder : placeholders) { |
| if (placeholder.getRef() == ref && placeholder.isToBeRendered()) { |
| // if there's a rendered placeholder, return |
| return; |
| } |
| } |
| |
| // no rendered placeholders around, unsubscribe |
| ViewReference reference = getViewReference((MPart) ref); |
| if (reference != null) { |
| reference.unsubscribe(); |
| } |
| } |
| } else if (element instanceof MPart) { |
| MPart part = (MPart) element; |
| // a part has been unrendered, check to see if the shared |
| // area needs to be unzoomed |
| unzoomSharedArea(part); |
| |
| if (CompatibilityEditor.MODEL_ELEMENT_ID.equals(part.getElementId())) { |
| EditorReference reference = getEditorReference(part); |
| if (reference != null) { |
| reference.unsubscribe(); |
| } |
| } |
| } |
| } |
| }; |
| |
| public String getHiddenItems() { |
| MPerspective perspective = getCurrentPerspective(); |
| if (perspective == null) |
| return ""; //$NON-NLS-1$ |
| |
| String result = perspective.getPersistedState().get(ModeledPageLayout.HIDDEN_ITEMS_KEY); |
| if (result == null) |
| return ""; //$NON-NLS-1$ |
| |
| return result; |
| } |
| |
| public void addHiddenItems(MPerspective perspective, String id) { |
| String hiddenIDs = perspective.getPersistedState().get(ModeledPageLayout.HIDDEN_ITEMS_KEY); |
| if (hiddenIDs == null) |
| hiddenIDs = ""; //$NON-NLS-1$ |
| |
| String persistedID = id + ","; //$NON-NLS-1$ |
| if (!hiddenIDs.contains(persistedID)) { |
| hiddenIDs = hiddenIDs + persistedID; |
| perspective.getPersistedState().put(ModeledPageLayout.HIDDEN_ITEMS_KEY, hiddenIDs); |
| } |
| } |
| |
| public void addHiddenItems(String id) { |
| MPerspective perspective = getCurrentPerspective(); |
| if (perspective == null) |
| return; |
| addHiddenItems(perspective, id); |
| } |
| |
| public void removeHiddenItems(MPerspective perspective, String id) { |
| String persistedID = id + ","; //$NON-NLS-1$ |
| |
| String hiddenIDs = perspective.getPersistedState().get(ModeledPageLayout.HIDDEN_ITEMS_KEY); |
| if (hiddenIDs == null) |
| return; |
| |
| String newValue = hiddenIDs.replaceFirst(persistedID, ""); //$NON-NLS-1$ |
| if (hiddenIDs.length() != newValue.length()) { |
| if (newValue.length() == 0) |
| perspective.getPersistedState().remove(ModeledPageLayout.HIDDEN_ITEMS_KEY); |
| else |
| perspective.getPersistedState().put(ModeledPageLayout.HIDDEN_ITEMS_KEY, |
| newValue); |
| } |
| } |
| |
| public void removeHiddenItems(String id) { |
| MPerspective perspective = getCurrentPerspective(); |
| if (perspective == null) |
| return; |
| removeHiddenItems(perspective, id); |
| } |
| |
| public void setNewShortcuts(List<String> wizards, String tagPrefix) { |
| MPerspective persp = getCurrentPerspective(); |
| if (persp == null) |
| return; |
| |
| List<String> existingNewWizards = new ArrayList<>(); |
| for (String tag : persp.getTags()) { |
| if (tag.contains(tagPrefix)) |
| existingNewWizards.add(tag); |
| } |
| |
| List<String> newWizards = new ArrayList<>(wizards.size()); |
| for (String wizardName : wizards) { |
| newWizards.add(tagPrefix + wizardName); |
| } |
| |
| persp.getTags().removeAll(existingNewWizards); |
| persp.getTags().addAll(newWizards); |
| } |
| |
| /** |
| * |
| */ |
| public void resetToolBarLayout() { |
| ICoolBarManager2 mgr = (ICoolBarManager2) legacyWindow.getCoolBarManager2(); |
| mgr.resetItemOrder(); |
| } |
| |
| /** |
| * Call {@link #firePartDeactivated(MPart)} if the passed part is the |
| * currently active part according to the part service. This method should |
| * only be called in the case of workbench shutdown, where E4 does not fire |
| * deactivate listeners on the active part. |
| * |
| * @param part |
| */ |
| public void firePartDeactivatedIfActive(MPart part) { |
| if (partService.getActivePart() == part) { |
| // At shutdown, e4 doesn't fire part deactivated on the active |
| // part. |
| firePartDeactivated(part); |
| } |
| } |
| |
| /** |
| * Add ToolItems for perspectives specified in "PERSPECTIVE_BAR_EXTRAS" |
| */ |
| private void createPerspectiveBarExtras() { |
| String persps = PrefUtil.getAPIPreferenceStore() |
| .getString(IWorkbenchPreferenceConstants.PERSPECTIVE_BAR_EXTRAS); |
| // e3 allowed spaces and commas as separator |
| String[] parts = persps.split("[, ]"); //$NON-NLS-1$ |
| Set<String> perspSet = new LinkedHashSet<>(); |
| for (String part : parts) { |
| part = part.trim(); |
| if (!part.isEmpty()) |
| perspSet.add(part); |
| } |
| |
| for (String perspId : perspSet) { |
| MPerspective persp = (MPerspective) modelService.find(perspId, window); |
| if (persp != null) |
| continue; // already in stack, i.e. has already been added above |
| IPerspectiveDescriptor desc = getDescriptorFor(perspId); |
| if (desc == null) |
| continue; // this perspective does not exist |
| persp = createPerspective(desc); |
| persp.setLabel(desc.getLabel()); |
| getPerspectiveStack().getChildren().add(persp); |
| // "add" fires Event, causes creation of ToolItem on perspective bar |
| } |
| } |
| |
| private IPerspectiveDescriptor getDescriptorFor(String id) { |
| IPerspectiveRegistry perspectiveRegistry = getWorkbenchWindow().getWorkbench().getPerspectiveRegistry(); |
| if (perspectiveRegistry instanceof PerspectiveRegistry) { |
| return ((PerspectiveRegistry) perspectiveRegistry).findPerspectiveWithId(id, false); |
| } |
| |
| return perspectiveRegistry.findPerspectiveWithId(id); |
| } |
| |
| } |