/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * 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
 *     Stefan Prieschl <stefan.prieschl@gmail.com> - Bug 374132
 *******************************************************************************/

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.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.emf.ecore.util.EcoreUtil;
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.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.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) {
				IWorkbenchPart workbenchPart = getWrappedPart((CompatibilityPart) client);
				if (workbenchPart == null) {
					return;
				}
				IWorkbenchPartSite site = workbenchPart.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) {
			IWorkbenchPart activePart = getWrappedPart((CompatibilityEditor) client);
			if (activePart == null) {
				return;
			}
			String activeId = activePart.getSite().getId();

			// find another editor that was last activated
			for (MPart previouslyActive : activationList) {
				if (previouslyActive != part) {
					Object object = previouslyActive.getObject();
					if (object instanceof CompatibilityEditor) {
						IWorkbenchPart workbenchPart = getWrappedPart((CompatibilityEditor) object);
						if (workbenchPart == null) {
							continue;
						}
						EditorSite site = (EditorSite) workbenchPart.getSite();
						String lastId = site.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 = getWrappedPart((CompatibilityPart) client);
			if (workbenchPart != null) {
				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);
		IContextService cs = legacyWindow.getService(IContextService.class);
		try {
			cs.deferUpdates(true);
			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());
			}
		} finally {
			cs.deferUpdates(false);
		}
	}

	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 = 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 IWorkingSet[] workingSets = new IWorkingSet[0];

	private IPropertyChangeListener workingSetPropertyChangeListener = 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 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();
			if (site != null) {
				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 = 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);
		if (ref == null) {
			throw new PartInitException(NLS.bind(WorkbenchMessages.ViewFactory_initException, viewId));
		}
		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(getWrappedPart(compatibilityView));
			}
			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(getWrappedPart(compatibilityView));
				}
			} 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, () -> 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;
		}

		IWorkbenchPart workbenchPart = getWrappedPart((CompatibilityPart) clientObject);
		if (save && workbenchPart != null) {
			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 = getWrappedPart((CompatibilityPart) object);
									if (workbenchPart == null) {
										continue;
									}
									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;
		}

		if (!legacyWindow.isClosing()) {
			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);
			}
		}

		for (ViewReference vr : viewReferences) {
			vr.setPage(null);
		}
		viewReferences.clear();
		for (EditorReference er : editorReferences) {
			er.setPage(null);
		}
		editorReferences.clear();
		sortedPerspectives.clear();
		modelToPerspectiveMapping.clear();

		if (unsetPage) {
			if (!legacyWindow.isClosing()) {
				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();
			if (!legacyWindow.isClosing()) {
				ContextInjectionFactory.uninject(this, window.getContext());
			}
		}
		if (workingSetPropertyChangeListener != null) {
			WorkbenchPlugin.getDefault().getWorkingSetManager()
					.removePropertyChangeListener(workingSetPropertyChangeListener);
			workingSetPropertyChangeListener = null;
		}
		_perspectiveStack = null;
		actionBars = null;
		actionSets = null;
		actionSwitcher.activePart = null;
		actionSwitcher.topEditor = null;
		activationList.clear();
		aggregateWorkingSet = null;
		application = null;
		broker = null;
		childrenHandler = null;
		composite = null;
		firingHandler = null;
		input = null;
		legacyWindow = null;
//		modelService = null;
		navigationHistory = null;
		pageChangedListener = null;
		partBeingActivated = null;
		partEvents.clear();
		partService = null;
		referenceRemovalEventHandler = null;
		selectionHandler = null;
		selectionService = null;
		sortedPerspectives.clear();
		tracker = null;
		widgetHandler = null;
//		window = null;
		workingSet = null;
		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() {
		legacyWindow = null;

// // 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() {
		if (partService == null) {
			return null;
		}
		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, (ob1, 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
				// at the part's curSharedRef since we're only considering
				// parts visible in the current perspective
				if (parts.contains(model) && !shouldNotRenderPart(model)) {
					// only rendered placeholders are valid view references
					visibleReferences.add(reference);
				}
			}
			return visibleReferences.toArray(new IViewReference[visibleReferences.size()]);
		}
		return new IViewReference[0];
	}

	/**
	 * @return {@code true} if the part should not be rendered or it has a current
	 *         shared reference that is not to be rendered <b>or</b> if a
	 *         placeholder for the part (in the current perspective) exists and is
	 *         not to be rendered. {@code false} otherwise, i.e. if the placeholders
	 *         of the part are to be rendered.
	 */
	private boolean shouldNotRenderPart(MPart part) {
		if (!part.isToBeRendered()) {
			return true;
		}
		MPlaceholder curSharedRef = part.getCurSharedRef();
		if (curSharedRef != null && !curSharedRef.isToBeRendered()) {
			return true;
		}
		MPlaceholder mPlaceholder = modelService.findPlaceholderFor(window, part);
		if (mPlaceholder != null && !mPlaceholder.isToBeRendered()) {
			return true;
		}
		return false;
	}

	/**
	 * 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 = 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 element1 = oldStack.getSelectedElement();
			if (element1 instanceof MPlaceholder) {
				hiddenParts.add((MPart) ((MPlaceholder) element1).getRef());
			} else if (element1 instanceof MPart) {
				hiddenParts.add((MPart) element1);
			}
		}

		for (MPartStack newStack : newStacks) {
			MStackElement element2 = newStack.getSelectedElement();
			if (element2 instanceof MPlaceholder) {
				visibleParts.add((MPart) ((MPlaceholder) element2).getRef());
			} else if (element2 instanceof MPart) {
				visibleParts.add((MPart) element2);
			}
		}

		List<MPart> ignoredParts = new ArrayList<>();
		for (MPart hiddenPart1 : hiddenParts) {
			if (visibleParts.contains(hiddenPart1)) {
				ignoredParts.add(hiddenPart1);
			}
		}

		hiddenParts.removeAll(ignoredParts);
		visibleParts.removeAll(ignoredParts);

		for (MPart hiddenPart2 : hiddenParts) {
			firePartHidden(hiddenPart2);
		}

		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(),
				() -> {
					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 = getWrappedPart((CompatibilityPart) object);
					if (workbenchPart == null) {
						continue;
					}
					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());

		MPerspective copy = (MPerspective) EcoreUtil.copy((EObject) visiblePerspective);

		List<MPlaceholder> elementsToHide = modelService.findElements(copy, null, MPlaceholder.class, null);
		for (MPlaceholder elementToHide : elementsToHide) {
			if (elementToHide.isToBeRendered()
					&& elementToHide.getRef().getTags().contains(IPresentationEngine.NO_RESTORE)) {
				elementToHide.setToBeRendered(false);
				updateSelectionAndParentVisibility(elementToHide);
			}
		}
		// remove placeholder refs and save as snippet
		modelService.cloneElement(copy, application);
		if (perspective instanceof PerspectiveDescriptor) {
			((PerspectiveDescriptor) perspective).setHasCustomDefinition(true);
		}

		UIEvents.publishEvent(UIEvents.UILifeCycle.PERSPECTIVE_SAVED, visiblePerspective);
	}

	private void updateSelectionAndParentVisibility(MUIElement element) {
		MElementContainer<MUIElement> parent = element.getParent();
		if (parent.getSelectedElement() == element) {
			parent.setSelectedElement(null);
		}
		int renderableChildren = modelService.countRenderableChildren(parent);
		if (renderableChildren == 0 && !modelService.isLastEditorStack(parent)) {
			parent.setToBeRendered(false);
			updateSelectionAndParentVisibility(parent);
		}
	}

	@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) {
				if (ph.isToBeRendered()) {
					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) {
				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, () -> {
			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) {
		String compoundId = PagePartSelectionTracker.getPartId(part);
		MPart mpart = partService.findPart(compoundId);
		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, (o1, 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 static final 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) {
		IWorkbenchPart wPart = ref.getPart(false);
		MPart part = ((EditorReference)ref).getModel();
		part.setVisible(true);

		//Workaround to get content visible. Otherwise the content sometimes is not rendered.
		MElementContainer<MUIElement> partStack = part.getParent();
		partStack.setSelectedElement(null);
		partStack.setSelectedElement(part);
		wPart.setFocus();
	}

	@Override
	public void hideEditor(IEditorReference ref) {
		MPart part = ((EditorReference)ref).getModel();
		part.setVisible(false);
	}

	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[i];
			IEditorInput curInput = 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 = getWrappedPart((CompatibilityPart) client);
			if (workbenchPart == null) {
				return;
			}
			final IWorkbenchPartReference partReference = getReference(workbenchPart);
			if (partReference == null) {
				WorkbenchPlugin.log(new RuntimeException("Reference is null in firePartActivated: " + part)); //$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 = getWrappedPart((CompatibilityPart) client);
			if (workbenchPart == null) {
				return;
			}
			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);
							}
						});
					}
				}
			}
		}
	}

	/**
	 * @param comPart
	 *            e4 wrapper around {@link IWorkbenchPart}
	 * @return can return null, in case {@link CompatibilityPart} was already
	 *         disposed
	 */
	private IWorkbenchPart getWrappedPart(CompatibilityPart comPart) {
		IWorkbenchPart part = comPart.getPart();
		if (part == null) {
			WorkbenchPlugin.log(new RuntimeException("Trying to access already disposed part: " //$NON-NLS-1$
					+ comPart));
		}
		return part;
	}

	public void firePartOpened(CompatibilityPart compatibilityPart) {
		final IWorkbenchPart part = getWrappedPart(compatibilityPart);
		final IWorkbenchPartReference partReference = compatibilityPart.getReference();

		if (part != null) {
			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 = getWrappedPart(compatibilityPart);
		final WorkbenchPartReference partReference = compatibilityPart.getReference();
		MPart model = partReference.getModel();

		if (part != null) {
			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 if (part != null) {
			editorReferences.remove(partReference);
		} else {
			// Whatever it was, try to cleanup the dirt
			viewReferences.remove(partReference);
			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 = getWrappedPart((CompatibilityPart) client);
			if (workbenchPart == null) {
				return;
			}
			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 = 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 = 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 = getWrappedPart((CompatibilityPart) client);
			if (workbenchPart == null) {
				return;
			}
			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 = getWrappedPart((CompatibilityPart) client);
			if (workbenchPart == null) {
				return;
			}
			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(), () -> {
				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 = 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 reference1 = getViewReference((MPart) ref);
				if (reference1 != null) {
					reference1.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 reference2 = getEditorReference(part);
				if (reference2 != null) {
					reference2.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);
	}

}
