/*******************************************************************************
 * Copyright (c) 2000, 2019 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
 *     Zhongwei Zhao - Bug 379495 - Two "Run" on top menu
 *     Patrick Chuong - Bug 391481 - Contributing perspectiveExtension, hiddenMenuItem
 *     								 removes a menu from multiple perspectives
 *     René Brandstetter - Bug 411821 - [QuickAccess] Contribute SearchField
 *                                      through a fragment or other means
 *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 431446, 433979, 440810, 441184, 472654, 486632
 *     Denis Zygann <d.zygann@web.de> - Bug 457390
 *     Andrey Loskutov <loskutov@gmx.de> - Bug 372799
 *     Axel Richard <axel.richard@obeo.fr> - Bug 354538
 *******************************************************************************/

package org.eclipse.ui.internal;

import java.lang.reflect.InvocationTargetException;
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.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.expressions.Expression;
import org.eclipse.core.expressions.ExpressionInfo;
import org.eclipse.core.expressions.IEvaluationContext;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
import org.eclipse.e4.core.commands.internal.HandlerServiceImpl;
import org.eclipse.e4.core.contexts.ContextFunction;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.contexts.RunAndTrack;
import org.eclipse.e4.core.di.InjectionException;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.core.services.log.Logger;
import org.eclipse.e4.ui.di.UIEventTopic;
import org.eclipse.e4.ui.internal.workbench.E4Workbench;
import org.eclipse.e4.ui.internal.workbench.PartServiceSaveHandler;
import org.eclipse.e4.ui.internal.workbench.URIHelper;
import org.eclipse.e4.ui.internal.workbench.renderers.swt.IUpdateService;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.MElementContainer;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.SideValue;
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.MCompositePart;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
import org.eclipse.e4.ui.model.application.ui.basic.MTrimElement;
import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
import org.eclipse.e4.ui.model.application.ui.menu.MToolControl;
import org.eclipse.e4.ui.model.internal.Position;
import org.eclipse.e4.ui.model.internal.PositionInfo;
import org.eclipse.e4.ui.services.EContextService;
import org.eclipse.e4.ui.workbench.IPresentationEngine;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.e4.ui.workbench.addons.splitteraddon.SplitHost;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.ISaveHandler;
import org.eclipse.e4.ui.workbench.modeling.IWindowCloseHandler;
import org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRenderer;
import org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRendererFilter;
import org.eclipse.e4.ui.workbench.renderers.swt.ToolBarManagerRenderer;
import org.eclipse.e4.ui.workbench.renderers.swt.TrimBarLayout;
import org.eclipse.e4.ui.workbench.renderers.swt.TrimmedPartLayout;
import org.eclipse.e4.ui.workbench.swt.factories.IRendererFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jface.action.CoolBarManager;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IContributionManagerOverrides;
import org.eclipse.jface.action.ICoolBarManager;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.StatusLineManager;
import org.eclipse.jface.action.SubContributionItem;
import org.eclipse.jface.commands.ActionHandler;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.internal.provisional.action.CoolBarManager2;
import org.eclipse.jface.internal.provisional.action.ICoolBarManager2;
import org.eclipse.jface.internal.provisional.action.IToolBarManager2;
import org.eclipse.jface.internal.provisional.action.ToolBarManager2;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.operation.ModalContext;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.osgi.util.NLS;
import org.eclipse.osgi.util.TextProcessor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.ActiveShellExpression;
import org.eclipse.ui.IPageListener;
import org.eclipse.ui.IPageService;
import org.eclipse.ui.IPartService;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveRegistry;
import org.eclipse.ui.ISaveablePart;
import org.eclipse.ui.ISaveablesLifecycleListener;
import org.eclipse.ui.ISaveablesSource;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.ISources;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.Saveable;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.application.ActionBarAdvisor;
import org.eclipse.ui.application.WorkbenchAdvisor;
import org.eclipse.ui.application.WorkbenchWindowAdvisor;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.dialogs.ListSelectionDialog;
import org.eclipse.ui.handlers.IHandlerActivation;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
import org.eclipse.ui.internal.actions.CommandAction;
import org.eclipse.ui.internal.commands.SlaveCommandService;
import org.eclipse.ui.internal.contexts.ContextService;
import org.eclipse.ui.internal.dialogs.cpd.CustomizePerspectiveDialog;
import org.eclipse.ui.internal.e4.compatibility.CompatibilityPart;
import org.eclipse.ui.internal.e4.compatibility.ModeledPageLayout;
import org.eclipse.ui.internal.e4.compatibility.SelectionService;
import org.eclipse.ui.internal.handlers.ActionCommandMappingService;
import org.eclipse.ui.internal.handlers.IActionCommandMappingService;
import org.eclipse.ui.internal.handlers.LegacyHandlerService;
import org.eclipse.ui.internal.menus.IActionSetsListener;
import org.eclipse.ui.internal.menus.LegacyActionPersistence;
import org.eclipse.ui.internal.menus.SlaveMenuService;
import org.eclipse.ui.internal.misc.UIListenerLogging;
import org.eclipse.ui.internal.progress.ProgressRegion;
import org.eclipse.ui.internal.provisional.application.IActionBarConfigurer2;
import org.eclipse.ui.internal.registry.IActionSetDescriptor;
import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
import org.eclipse.ui.internal.registry.UIExtensionTracker;
import org.eclipse.ui.internal.services.EvaluationReference;
import org.eclipse.ui.internal.services.IServiceLocatorCreator;
import org.eclipse.ui.internal.services.IWorkbenchLocationService;
import org.eclipse.ui.internal.services.ServiceLocator;
import org.eclipse.ui.internal.services.WorkbenchLocationService;
import org.eclipse.ui.internal.util.PrefUtil;
import org.eclipse.ui.keys.IBindingService;
import org.eclipse.ui.menus.IMenuService;
import org.eclipse.ui.model.WorkbenchPartLabelProvider;
import org.eclipse.ui.services.IEvaluationService;
import org.eclipse.ui.services.IServiceScopes;
import org.eclipse.ui.views.IViewDescriptor;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;

/**
 * A window within the workbench.
 */
public class WorkbenchWindow implements IWorkbenchWindow {

	/**
	 * The 'elementId' of the spacer used to right-align it in the trim
	 */
	public static final String PERSPECTIVE_SPACER_ID = "PerspectiveSpacer"; //$NON-NLS-1$

	public static final String STATUS_LINE_ID = "org.eclipse.ui.StatusLine"; //$NON-NLS-1$

	public static final String TRIM_CONTRIBUTION_URI = "bundleclass://org.eclipse.ui.workbench/org.eclipse.ui.internal.StandardTrim"; //$NON-NLS-1$

	private static final String COMMAND_ID_TOGGLE_COOLBAR = "org.eclipse.ui.ToggleCoolbarAction"; //$NON-NLS-1$

	public static final String ACTION_SET_CMD_PREFIX = "AS::"; //$NON-NLS-1$

	private static final String PERSISTED_STATE_RESTORED = "isRestored"; //$NON-NLS-1$

	@Inject
	private IWorkbench workbench;
	@Inject
	private MTrimmedWindow model;
	@Inject
	private IPresentationEngine engine;

	@Inject
	private IRendererFactory rendererFactory;

	@Inject
	private MApplication application;

	@Inject
	EModelService modelService;

	@Inject
	private IEventBroker eventBroker;

	@Inject
	@Optional
	private Logger logger;

	@Inject
	private IExtensionRegistry extensionRegistry;

	private WorkbenchPage page;

	private WorkbenchWindowAdvisor windowAdvisor;

	private ActionBarAdvisor actionBarAdvisor;

	private MenuManagerRenderer renderer;

	private MMenu mainMenu;

	private PageListenerList pageListeners = new PageListenerList();

	private PerspectiveListenerList perspectiveListeners = new PerspectiveListenerList();

	private PartService partService = new WWinPartService();

	private WWinActionBars actionBars;

	private boolean updateDisabled = false;

	private boolean closing = false;

	private boolean shellActivated = false;

	ProgressRegion progressRegion = null;

	private List<MTrimElement> workbenchTrimElements = new ArrayList<>();

	private Map<MToolControl, IConfigurationElement> iceMap = new HashMap<>();

	public IConfigurationElement getICEFor(MToolControl mtc) {
		return iceMap.get(mtc);
	}

	/**
	 * The map of services maintained by the workbench window. These services are
	 * initialized when the workbench window is being constructed by dependency
	 * injection.
	 */
	private ServiceLocator serviceLocator;

	/**
	 * Bit flags indication which submenus (New, Show Views, ...) this window
	 * contains. Initially none.
	 *
	 * @since 3.0
	 */
	private int submenus = 0x00;

	/**
	 * Object for configuring this workbench window. Lazily initialized to an
	 * instance unique to this window.
	 *
	 * @since 3.0
	 */
	private WorkbenchWindowConfigurer windowConfigurer = null;

	/**
	 * List of generic property listeners.
	 *
	 * @since 3.3
	 */
	private ListenerList<IPropertyChangeListener> genericPropertyListeners = new ListenerList<>();

	private IAdaptable input;

	private IPerspectiveDescriptor perspective;

	private EventHandler windowWidgetHandler = event -> {
		if (event.getProperty(UIEvents.EventTags.ELEMENT) == model
				&& event.getProperty(UIEvents.EventTags.NEW_VALUE) == null) {
			// HandledContributionItem.toolItemUpdater.removeWindowRunnable(menuUpdater);
			this.manageChanges = false;
			this.canUpdateMenus = false;
			this.menuUpdater = null;

			MMenu menu = model.getMainMenu();
			if (menu != null) {
				engine.removeGui(menu);
				model.setMainMenu(null);
			}

			eventBroker.unsubscribe(this.windowWidgetHandler);
		}
	};

	static final String TEXT_DELIMITERS = TextProcessor.getDefaultDelimiters() + "-"; //$NON-NLS-1$

	/** Marks the beginning of a tag which contains positioning information. */
	static final String MOVE_TAG = "move_"; //$NON-NLS-1$

	/**
	 * Ordered list of element IDs which belong to the QuickAccess
	 * {@link MToolControl}s.
	 *
	 * <p>
	 * Element IDs which belong to QuickAccess:
	 * </p>
	 * <ul>
	 * <li><code>Spacer Glue</code></li>
	 * <li><code>SearchField</code></li>
	 * <li><code>Search-PS Glue</code></li>
	 * </ul>
	 */
	private static final List<String> QUICK_ACCESS_ELEMENT_IDS = Collections
			.unmodifiableList(Arrays.asList("Spacer Glue", "SearchField", "Search-PS Glue")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

	/**
	 * Coolbar visibility change property.
	 *
	 * @since 3.3
	 */
	public static final String PROP_COOLBAR_VISIBLE = "coolbarVisible"; //$NON-NLS-1$

	/**
	 * Perspective bar visibility change property.
	 *
	 * @since 3.3
	 */
	public static final String PROP_PERSPECTIVEBAR_VISIBLE = "perspectiveBarVisible"; //$NON-NLS-1$

	/**
	 * The status line visibility change property. for internal use only.
	 *
	 * @since 3.4
	 */
	public static final String PROP_STATUS_LINE_VISIBLE = "statusLineVisible"; //$NON-NLS-1$

	/**
	 * Constant (bit mask) indicating which the Show View submenu is probably
	 * present somewhere in this window.
	 *
	 * @see #addSubmenu
	 * @since 3.0
	 */
	public static final int SHOW_VIEW_SUBMENU = 0x01;

	/**
	 * Constant (bit mask) indicating which the Open Perspective submenu is probably
	 * present somewhere in this window.
	 *
	 * @see #addSubmenu
	 * @since 3.0
	 */
	public static final int OPEN_PERSPECTIVE_SUBMENU = 0x02;

	/**
	 * Constant (bit mask) indicating which the New Wizard submenu is probably
	 * present somewhere in this window.
	 *
	 * @see #addSubmenu
	 * @since 3.0
	 */
	public static final int NEW_WIZARD_SUBMENU = 0x04;

	/**
	 * Remembers that this window contains the given submenu.
	 *
	 * @param type the type of submenu, one of: {@link #NEW_WIZARD_SUBMENU
	 *             NEW_WIZARD_SUBMENU}, {@link #OPEN_PERSPECTIVE_SUBMENU
	 *             OPEN_PERSPECTIVE_SUBMENU}, {@link #SHOW_VIEW_SUBMENU
	 *             SHOW_VIEW_SUBMENU}
	 * @see #containsSubmenu
	 * @since 3.0
	 */
	public void addSubmenu(int type) {
		submenus |= type;
	}

	/**
	 * Checks to see if this window contains the given type of submenu.
	 *
	 * @param type the type of submenu, one of: {@link #NEW_WIZARD_SUBMENU
	 *             NEW_WIZARD_SUBMENU}, {@link #OPEN_PERSPECTIVE_SUBMENU
	 *             OPEN_PERSPECTIVE_SUBMENU}, {@link #SHOW_VIEW_SUBMENU
	 *             SHOW_VIEW_SUBMENU}
	 * @return <code>true</code> if window contains submenu, <code>false</code>
	 *         otherwise
	 * @see #addSubmenu
	 * @since 3.0
	 */
	public boolean containsSubmenu(int type) {
		return ((submenus & type) != 0);
	}

	/**
	 * Constant indicating that all the actions bars should be filled.
	 *
	 * @since 3.0
	 */
	private static final int FILL_ALL_ACTION_BARS = ActionBarAdvisor.FILL_MENU_BAR | ActionBarAdvisor.FILL_COOL_BAR
			| ActionBarAdvisor.FILL_STATUS_LINE;

	/**
	 * Creates and initializes a new workbench window.
	 *
	 * @param input the input for this workbench window
	 * @param pers  the perspective to initialize this workbench window with
	 */
	public WorkbenchWindow(IAdaptable input, IPerspectiveDescriptor pers) {
		this.input = input;
		perspective = pers;
	}

	@PostConstruct
	public void setup() {
		try {
			// if workbench window is opened as a result of command execution,
			// the context in which the new workbench window's commands are
			// initialized has to to match the workbench context
			final IEclipseContext windowContext = model.getContext();
			HandlerServiceImpl.push(windowContext.getParent(), null);

			// Initialize a previous 'saved' state if applicable. We no longer
			// update the preference store.
			if (getModel().getPersistedState().containsKey(IPreferenceConstants.COOLBAR_VISIBLE)) {
				this.coolBarVisible = Boolean
						.parseBoolean(getModel().getPersistedState().get(IPreferenceConstants.COOLBAR_VISIBLE));
			} else {
				this.coolBarVisible = PrefUtil.getInternalPreferenceStore()
						.getBoolean(IPreferenceConstants.COOLBAR_VISIBLE);
				getModel().getPersistedState().put(IPreferenceConstants.COOLBAR_VISIBLE,
						Boolean.toString(this.coolBarVisible));
			}
			if (getModel().getPersistedState().containsKey(IPreferenceConstants.PERSPECTIVEBAR_VISIBLE)) {
				this.perspectiveBarVisible = Boolean
						.parseBoolean(getModel().getPersistedState().get(IPreferenceConstants.PERSPECTIVEBAR_VISIBLE));
			} else {
				this.perspectiveBarVisible = PrefUtil.getInternalPreferenceStore()
						.getBoolean(IPreferenceConstants.PERSPECTIVEBAR_VISIBLE);
				getModel().getPersistedState().put(IPreferenceConstants.PERSPECTIVEBAR_VISIBLE,
						Boolean.toString(this.perspectiveBarVisible));
			}

			IServiceLocatorCreator slc = workbench.getService(IServiceLocatorCreator.class);
			this.serviceLocator = (ServiceLocator) slc.createServiceLocator(workbench, null, () -> {
				final Shell shell = getShell();
				if (shell != null && !shell.isDisposed()) {
					close();
				}
			}, windowContext);

			windowContext.set(IExtensionTracker.class.getName(), new ContextFunction() {
				@Override
				public Object compute(IEclipseContext context, String contextKey) {
					if (tracker == null) {
						tracker = new UIExtensionTracker(getWorkbench().getDisplay());
					}
					return tracker;
				}
			});

			windowContext.set(IWindowCloseHandler.class.getName(), (IWindowCloseHandler) window -> getWindowAdvisor().preWindowShellClose() && WorkbenchWindow.this.close());

			final ISaveHandler defaultSaveHandler = windowContext.get(ISaveHandler.class);
			final PartServiceSaveHandler localSaveHandler = new WWinPartServiceSaveHandler() {
				@Override
				public Save promptToSave(MPart dirtyPart) {
					Object object = dirtyPart.getObject();
					if (object instanceof CompatibilityPart) {
						IWorkbenchPart part = ((CompatibilityPart) object).getPart();
						ISaveablePart saveable = SaveableHelper.getSaveable(part);
						if (saveable != null) {
							if (!saveable.isSaveOnCloseNeeded()) {
								return Save.NO;
							}
							return SaveableHelper.savePart(saveable, part, WorkbenchWindow.this, true) ? Save.NO
									: Save.CANCEL;
						}
					}
					return defaultSaveHandler.promptToSave(dirtyPart);
				}

				@Override
				public Save[] promptToSave(Collection<MPart> dirtyParts) {
					LabelProvider labelProvider = new LabelProvider() {
						@Override
						public String getText(Object element) {
							return ((MPart) element).getLocalizedLabel();
						}
					};
					List<MPart> parts = new ArrayList<>(dirtyParts);
					ListSelectionDialog dialog = new ListSelectionDialog(getShell(), parts,
							ArrayContentProvider.getInstance(), labelProvider,
							WorkbenchMessages.EditorManager_saveResourcesMessage);
					dialog.setInitialSelections(parts.toArray());
					dialog.setTitle(WorkbenchMessages.EditorManager_saveResourcesTitle);
					if (dialog.open() == IDialogConstants.CANCEL_ID) {
						return new Save[] { Save.CANCEL };
					}

					Object[] toSave = dialog.getResult();
					Save[] retSaves = new Save[parts.size()];
					Arrays.fill(retSaves, Save.NO);
					for (int i = 0; i < retSaves.length; i++) {
						MPart part = parts.get(i);
						for (Object o : toSave) {
							if (o == part) {
								retSaves[i] = Save.YES;
								break;
							}
						}
					}
					return retSaves;
				}

				@Override
				public boolean save(MPart dirtyPart, boolean confirm) {
					Object object = dirtyPart.getObject();
					if (object instanceof CompatibilityPart) {
						IWorkbenchPart workbenchPart = ((CompatibilityPart) object).getPart();
						if (SaveableHelper.isSaveable(workbenchPart)) {
							SaveablesList saveablesList = (SaveablesList) PlatformUI.getWorkbench()
									.getService(ISaveablesLifecycleListener.class);
							Object saveResult = saveablesList.preCloseParts(Collections.singletonList(workbenchPart),
									true, WorkbenchWindow.this);
							return saveResult != null;
						}
					} else if (isSaveOnCloseNotNeededSplitEditorPart(dirtyPart)) {
						return true;
					}
					return super.save(dirtyPart, confirm);
				}

				private boolean saveParts(ArrayList<MPart> dirtyParts, Save[] decisions) {
					if (decisions == null || decisions.length == 0) {
						super.saveParts(dirtyParts, true);
					}
					if (dirtyParts.size() != decisions.length) {
						for (Save decision : decisions) {
							if (decision == Save.CANCEL) {
								return false;
							}
						}
					}
					List<MPart> dirtyPartsList = Collections.unmodifiableList(new ArrayList<>(dirtyParts));
					for (Save decision : decisions) {
						if (decision == Save.CANCEL) {
							return false;
						}
					}

					for (int i = 0; i < decisions.length; i++) {
						if (decisions[i] == Save.YES) {
							if (!save(dirtyPartsList.get(i), false)) {
								return false;
							}
						}
					}
					return true;
				}

				private boolean saveMixedParts(ArrayList<MPart> nonCompParts, ArrayList<IWorkbenchPart> compParts,
						boolean confirm, boolean addNonPartSources) {
					SaveablesList saveablesList = (SaveablesList) PlatformUI.getWorkbench()
							.getService(ISaveablesLifecycleListener.class);
					if (!confirm) {
						boolean saved = super.saveParts(nonCompParts, confirm);
						Object saveResult = saveablesList.preCloseParts(compParts, true, WorkbenchWindow.this);
						return ((saveResult != null) && saved);
					}
					LabelProvider labelProvider = new LabelProvider() {
						WorkbenchPartLabelProvider workbenchLabelProvider = new WorkbenchPartLabelProvider();

						@Override
						public String getText(Object element) {
							if (element instanceof Saveable) {
								return workbenchLabelProvider.getText(element);
							}
							return ((MPart) element).getLocalizedLabel();
						}
					};
					ArrayList<Object> listParts = new ArrayList<>();
					Map<IWorkbenchPart, List<Saveable>> saveableMap = saveablesList.getSaveables(compParts);
					listParts.addAll(nonCompParts);
					LinkedHashSet<Saveable> saveablesSet = new LinkedHashSet<>();
					for (IWorkbenchPart workbenchPart : compParts) {
						List<Saveable> list = saveableMap.get(workbenchPart);
						if (list != null) {
							saveablesSet.addAll(list);
						}
					}
					if (addNonPartSources) {
						for (ISaveablesSource nonPartSource : saveablesList.getNonPartSources()) {
							Saveable[] saveables = nonPartSource.getSaveables();
							for (Saveable saveable : saveables) {
								if (saveable.isDirty()) {
									saveablesSet.add(saveable);
								}
							}
						}
					}
					listParts.addAll(saveablesSet);
					ListSelectionDialog dialog = new ListSelectionDialog(getShell(), listParts,
							ArrayContentProvider.getInstance(), labelProvider,
							WorkbenchMessages.EditorManager_saveResourcesMessage);
					dialog.setInitialSelections(listParts.toArray());
					dialog.setTitle(WorkbenchMessages.EditorManager_saveResourcesTitle);
					if (dialog.open() == IDialogConstants.CANCEL_ID) {
						return false;
					}

					Object[] toSave = dialog.getResult();
					Save[] nonCompatSaves = new Save[nonCompParts.size()];
					Save[] compatSaves = new Save[saveablesSet.size()];
					Arrays.fill(nonCompatSaves, Save.NO);
					Arrays.fill(compatSaves, Save.NO);
					for (int i = 0; i < nonCompatSaves.length; i++) {
						MPart part = nonCompParts.get(i);
						for (Object o : toSave) {
							if (o == part) {
								nonCompatSaves[i] = Save.YES;
								break;
							}
						}
					}
					Map<Saveable, Save> saveOptionMap = new HashMap<>();
					for (Saveable saveable : saveablesSet) {
						boolean found = false;
						for (Object o : toSave) {
							if (o == saveable) {
								saveOptionMap.put(saveable, Save.YES);
								found = true;
								break;
							}
						}
						if (!found) {
							saveOptionMap.put(saveable, Save.NO);
						}
					}
					boolean saved = saveParts(nonCompParts, nonCompatSaves);
					if (!saved) {
						return saved;
					}
					Object saveResult = saveablesList.preCloseParts(compParts, false, true, WorkbenchWindow.this,
							saveOptionMap);
					return ((saveResult != null) && saved);
				}

				private 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();
						}
					}
				}

				private void removeSaveOnCloseNotNeededSplitEditorParts(List<MPart> parts) {
					for (Iterator<MPart> it = parts.iterator(); it.hasNext();) {
						MPart part = it.next();
						if (isSaveOnCloseNotNeededSplitEditorPart(part)) {
							it.remove();
						}
					}
				}

				private boolean isSaveOnCloseNotNeededSplitEditorPart(MPart part) {
					boolean notNeeded = false;
					if (part instanceof MCompositePart
							&& SplitHost.SPLIT_HOST_CONTRIBUTOR_URI.equals(part.getContributionURI())) {
						MCompositePart compPart = (MCompositePart) part;
						List<MPart> elements = modelService.findElements(compPart, null, MPart.class);
						if (elements != null && elements.size() > 1) {
							elements.remove(0);
							for (MPart mpart : elements) {
								Object object = mpart.getObject();
								if (object instanceof CompatibilityPart) {
									IWorkbenchPart workbenchPart = ((CompatibilityPart) object).getPart();
									if (!SaveableHelper.isSaveable(workbenchPart)) {
										notNeeded = true;
									} else {
										ISaveablePart saveable = SaveableHelper.getSaveable(workbenchPart);
										if (saveable == null || !saveable.isSaveOnCloseNeeded()) {
											notNeeded = true;
										} else {
											notNeeded = false;
											break;
										}
									}
								} else {
									notNeeded = false;
									break;
								}
							}
						}
					}
					return notNeeded;
				}

				@Override
				public boolean saveParts(Collection<MPart> dirtyParts, boolean confirm, boolean closing, boolean addNonPartSources) {
					ArrayList<IWorkbenchPart> saveableParts = new ArrayList<>();
					ArrayList<MPart> nonCompatibilityParts = new ArrayList<>();
					for (MPart part : dirtyParts) {
						Object object = part.getObject();
						if (object instanceof CompatibilityPart) {
							IWorkbenchPart workbenchPart = ((CompatibilityPart) object).getPart();
							if (SaveableHelper.isSaveable(workbenchPart)) {
								saveableParts.add(workbenchPart);
							}
						} else {
							nonCompatibilityParts.add(part);
						}
					}
					if (!saveableParts.isEmpty() && closing) {
						removeSaveOnCloseNotNeededParts(saveableParts);
					}
					if (!nonCompatibilityParts.isEmpty() && closing) {
						removeSaveOnCloseNotNeededSplitEditorParts(nonCompatibilityParts);
					}
					if (saveableParts.isEmpty()) {
						if (nonCompatibilityParts.isEmpty()) {
							// nothing to save
							return true;
						}
						return super.saveParts(nonCompatibilityParts, confirm);
					} else if (!nonCompatibilityParts.isEmpty()) {
						return saveMixedParts(nonCompatibilityParts, saveableParts, confirm, addNonPartSources);
					}

					SaveablesList saveablesList = (SaveablesList) PlatformUI.getWorkbench()
							.getService(ISaveablesLifecycleListener.class);
					Object saveResult = saveablesList.preCloseParts(saveableParts, addNonPartSources, true,
							WorkbenchWindow.this, WorkbenchWindow.this);
					return (saveResult != null);
				}

				@Override
				public boolean saveParts(Collection<MPart> dirtyParts, boolean confirm) {
					return saveParts(dirtyParts, confirm, false, false);
				}
			};
			localSaveHandler.logger = logger;
			windowContext.set(ISaveHandler.class, localSaveHandler);

			windowContext.set(IWorkbenchWindow.class.getName(), this);
			windowContext.set(IPageService.class, this);
			windowContext.set(IPartService.class, partService);

			windowContext.set(ISources.ACTIVE_WORKBENCH_WINDOW_NAME, this);
			windowContext.set(ISources.ACTIVE_WORKBENCH_WINDOW_SHELL_NAME, getShell());
			EContextService cs = windowContext.get(EContextService.class);
			cs.activateContext(IContextService.CONTEXT_ID_WINDOW);
			cs.getActiveContextIds();

			initializeDefaultServices();

			/*
			 * Remove the second QuickAccess control if an older workspace is opened.
			 *
			 * An older workspace will create an ApplicationModel which already contains the
			 * QuickAccess elements, from the old "popuolateTopTrimContribution()" method.
			 * The new implementation of this method doesn't add the QuickAccess elements
			 * anymore but an old workbench.xmi still has these entries in it and so they
			 * need to be removed.
			 */
			cleanLegacyQuickAccessContribution();

			// register with the tracker

			fireWindowOpening();
			configureShell(getShell(), windowContext);

			try {
				page = new WorkbenchPage(this, input);
			} catch (WorkbenchException e) {
				WorkbenchPlugin.log(e);
			}
			menuOverride = new MenuOverrides(page);
			toolbarOverride = new ToolbarOverrides(page);

			ContextInjectionFactory.inject(page, model.getContext());
			windowContext.set(IWorkbenchPage.class, page);

			menuManager.setOverrides(menuOverride);
			((CoolBarToTrimManager) getCoolBarManager2()).setOverrides(toolbarOverride);

			// Fill the action bars
			fillActionBars(FILL_ALL_ACTION_BARS);
			firePageOpened();

			populateTopTrimContributions();
			populateBottomTrimContributions();

			// Trim gets populated during rendering (?) so make sure we have al/
			// sides. See bug 383269 for details
			modelService.getTrim(model, SideValue.LEFT);
			modelService.getTrim(model, SideValue.RIGHT);

			// move the QuickAccess ToolControl to the correct position (only if
			// it exists)
			positionQuickAccess();

			Shell shell = (Shell) model.getWidget();
			if (model.getMainMenu() == null) {
				mainMenu = modelService.createModelElement(MMenu.class);
				mainMenu.setElementId(IWorkbenchConstants.MAIN_MENU_ID);
				mainMenu.getPersistedState().put(org.eclipse.e4.ui.workbench.IWorkbench.PERSIST_STATE,
						Boolean.FALSE.toString());

				renderer = (MenuManagerRenderer) rendererFactory.getRenderer(mainMenu, null);
				renderer.linkModelToManager(mainMenu, menuManager);
				renderer.reconcileManagerToModel(menuManager, mainMenu);
				model.setMainMenu(mainMenu);
				final Menu menu = (Menu) engine.createGui(mainMenu, model.getWidget(), model.getContext());
				shell.setMenuBar(menu);

				menuUpdater = () -> {
					try {
						if (model.getMainMenu() == null || model.getWidget() == null || menu.isDisposed()
								|| mainMenu.getWidget() == null) {
							return;
						}
						MenuManagerRendererFilter.updateElementVisibility(mainMenu, renderer, menuManager,
								windowContext.getActiveLeaf(), 1, false);
						menuManager.update(true);
					} finally {
						canUpdateMenus = true;
					}
				};

				RunAndTrack menuChangeManager = new RunAndTrack() {
					@Override
					public boolean changed(IEclipseContext context) {
						ExpressionInfo info = new ExpressionInfo();
						IEclipseContext leafContext = windowContext.getActiveLeaf();
						MenuManagerRendererFilter.collectInfo(info, mainMenu, renderer, leafContext, true);
						// if one of these variables change, re-run the RAT
						for (String name : info.getAccessedVariableNames()) {
							leafContext.get(name);
						}
						if (canUpdateMenus && workbench.getDisplay() != null) {
							canUpdateMenus = false;
							workbench.getDisplay().asyncExec(menuUpdater);
						}
						return manageChanges;
					}
				};
				windowContext.runAndTrack(menuChangeManager);
			}

			eventBroker.subscribe(UIEvents.UIElement.TOPIC_WIDGET, windowWidgetHandler);

			boolean newWindow = setupPerspectiveStack(windowContext);
			partService.setPage(page);
			page.setPerspective(perspective);
			firePageActivated();

			if (newWindow) {
				page.fireInitialPartVisibilityEvents();
			} else {
				page.updatePerspectiveActionSets();
			}
			updateActionSets();

			IPreferenceStore preferenceStore = PrefUtil.getAPIPreferenceStore();
			boolean enableAnimations = preferenceStore.getBoolean(IWorkbenchPreferenceConstants.ENABLE_ANIMATIONS);
			preferenceStore.setValue(IWorkbenchPreferenceConstants.ENABLE_ANIMATIONS, false);

			// Hack!! don't show the intro if there's more than one open
			// perspective
			List<MPerspective> persps = modelService.findElements(model, null, MPerspective.class, null);
			if (persps.size() > 1) {
				PrefUtil.getAPIPreferenceStore().setValue(IWorkbenchPreferenceConstants.SHOW_INTRO, false);
				PrefUtil.saveAPIPrefs();
			}

			if (Boolean.parseBoolean(getModel().getPersistedState().get(PERSISTED_STATE_RESTORED))) {
				SafeRunnable.run(new SafeRunnable() {

					@Override
					public void run() throws Exception {
						getWindowAdvisor().postWindowRestore();
					}
				});
			} else {
				getModel().getPersistedState().put(PERSISTED_STATE_RESTORED, Boolean.TRUE.toString());
			}

			getWindowAdvisor().postWindowCreate();
			getWindowAdvisor().openIntro();

			preferenceStore.setValue(IWorkbenchPreferenceConstants.ENABLE_ANIMATIONS, enableAnimations);

			getShell().setData(this);
			trackShellActivation();
			/**
			 * When SWT zoom changes for primary monitor, prompt user to restart Eclipse to
			 * apply the changes.
			 */
			getShell().addListener(SWT.ZoomChanged, event -> {
				if (getShell().getDisplay().getPrimaryMonitor().equals(getShell().getMonitor())) {
					int dialogResponse = MessageDialog.open(MessageDialog.QUESTION, getShell(),
							WorkbenchMessages.Workbench_zoomChangedTitle,
							WorkbenchMessages.Workbench_zoomChangedMessage, SWT.NONE,
							WorkbenchMessages.Workbench_zoomChangedRestart, IDialogConstants.NO_LABEL);
					if (event.doit && dialogResponse == 0) {
						getWorkbenchImpl().restart(true);
					}
				}
			});

		} finally {
			HandlerServiceImpl.pop();
		}
	}

	@PreDestroy
	void preDestroy() {
		if (mainMenu != null) {
			renderer.clearModelToManager(mainMenu, menuManager);
			mainMenu = null;
		}
		renderer = null;
	}

	private void configureShell(Shell shell, IEclipseContext context) {
		String title = getWindowConfigurer().basicGetTitle();
		if (title != null) {
			shell.setText(TextProcessor.process(title, TEXT_DELIMITERS));
		}
		workbench.getHelpSystem().setHelp(shell, IWorkbenchHelpContextIds.WORKBENCH_WINDOW);

		IContextService contextService = context.get(IContextService.class);
		contextService.registerShell(shell, IContextService.TYPE_WINDOW);
		if (model.getContext().get(E4Workbench.NO_SAVED_MODEL_FOUND) != null) {
			Point initialSize = getWindowConfigurer().getInitialSize();
			Rectangle bounds = shell.getBounds();
			// actually set the shell size, so that setting the
			// menuBar on the shell doesn't override the model changes.
			bounds.width = initialSize.x;
			bounds.height = initialSize.y;
			shell.setBounds(bounds);
		}
	}

	private boolean setupPerspectiveStack(IEclipseContext context) {
		IPerspectiveRegistry registry = getWorkbench().getPerspectiveRegistry();
		String forcedPerspectiveId = (String) context.get(E4Workbench.FORCED_PERSPECTIVE_ID);

		if (forcedPerspectiveId != null) {
			perspective = registry.findPerspectiveWithId(forcedPerspectiveId);
		}

		List<MPerspectiveStack> perspStackList = modelService.findElements(model, null, MPerspectiveStack.class, null);
		MPerspective selectedPersp = null;

		if (!perspStackList.isEmpty()) {
			selectedPersp = perspStackList.get(0).getSelectedElement();
		}

		if (forcedPerspectiveId == null && selectedPersp != null) {
			perspective = registry.findPerspectiveWithId(selectedPersp.getElementId());
		}

		if (perspective == null) {
			perspective = registry.findPerspectiveWithId(registry.getDefaultPerspective());
		}

		// the perspective stack doesn't have a selected element what means that
		// we have a new window
		return selectedPersp == null;
	}

	private boolean manageChanges = true;
	private boolean canUpdateMenus = true;

	void populateTopTrimContributions() {
		getCoolBarManager2().update(true);
		getCoolBarManager2().add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));

		final MTrimBar trimBar = getTopTrim();
		// TODO why aren't these added as trim contributions
		// that would remove everything from this method except the fill(*)
		/*
		 * Reason Why: The setup() method which calls this method also calls the
		 * ActionBarAdvisor to fill the TopTrim-Bar. Both this and the ActionBarAdvisor
		 * fill method will be called after the entire application model and all its
		 * fragments have been build already. This leads to the effect that all the
		 * elements contributed via the application model would be placed in front of
		 * the elements contributed by the setup() method. (Means all the "Save",
		 * "Save All", and so on, buttons which are normally placed at the beginning of
		 * the trimbar (left) would be moved to the end of it (right).)
		 */
		MToolControl spacerControl = (MToolControl) modelService.find(PERSPECTIVE_SPACER_ID, model);
		if (spacerControl == null) {
			spacerControl = modelService.createModelElement(MToolControl.class);
			spacerControl.setElementId(PERSPECTIVE_SPACER_ID);
			spacerControl.setContributionURI(
					"bundleclass://org.eclipse.e4.ui.workbench.renderers.swt/org.eclipse.e4.ui.workbench.renderers.swt.LayoutModifierToolControl"); //$NON-NLS-1$
			spacerControl.getTags().add(TrimBarLayout.SPACER);
			spacerControl.getTags().add("SHOW_RESTORE_MENU"); //$NON-NLS-1$
			trimBar.getChildren().add(spacerControl);
		} else if (!spacerControl.getTags().contains("SHOW_RESTORE_MENU")) { //$NON-NLS-1$
			spacerControl.getTags().add("SHOW_RESTORE_MENU"); //$NON-NLS-1$
		}

		MToolControl switcherControl = (MToolControl) modelService.find("PerspectiveSwitcher", model); //$NON-NLS-1$
		if (switcherControl == null && getWindowConfigurer().getShowPerspectiveBar()) {
			switcherControl = modelService.createModelElement(MToolControl.class);
			switcherControl.setToBeRendered(getWindowConfigurer().getShowPerspectiveBar());
			switcherControl.setElementId("PerspectiveSwitcher"); //$NON-NLS-1$
			switcherControl.getTags().add(IPresentationEngine.DRAGGABLE);
			switcherControl.getTags().add("HIDEABLE"); //$NON-NLS-1$
			switcherControl.getTags().add("SHOW_RESTORE_MENU"); //$NON-NLS-1$
			switcherControl.setContributionURI(
					"bundleclass://org.eclipse.ui.workbench/org.eclipse.e4.ui.workbench.addons.perspectiveswitcher.PerspectiveSwitcher"); //$NON-NLS-1$
			trimBar.getChildren().add(switcherControl);
		} else if (switcherControl != null) {
			if (!getWindowConfigurer().getShowPerspectiveBar()) {
				trimBar.getChildren().remove(switcherControl);
			} else {
				List<String> tags = switcherControl.getTags();
				if (!tags.contains("HIDEABLE")) { //$NON-NLS-1$
					tags.add("HIDEABLE"); //$NON-NLS-1$
				}
				if (!tags.contains("SHOW_RESTORE_MENU")) { //$NON-NLS-1$
					tags.add("SHOW_RESTORE_MENU"); //$NON-NLS-1$
				}
			}
		}

		// render now after everything has been added so contributions can be
		// inserted in the right place
		updateLayoutDataForContents();
	}

	/**
	 * Removes the "legacy" QuickAccess related fields from the ApplicationModel.
	 * <p>
	 * The "legacy" QuickAccess fields exist in the ApplicationModel if an older
	 * workspace is opened which was build before the QuickAccess was contributed
	 * via e4xmi-fragment.
	 * </p>
	 */
	private void cleanLegacyQuickAccessContribution() {
		for (String quickAccessElementId : QUICK_ACCESS_ELEMENT_IDS) {
			MToolControl legacyElement = (MToolControl) modelService.find(quickAccessElementId, model);
			if (legacyElement != null) {
				EcoreUtil.remove((EObject) legacyElement);
			}
		}
	}

	/**
	 * Moves the QucickAccess related fields to the wanted position.
	 * <p>
	 * If the elements "Spacer Glue", "SearchField" and "Search-PS Glue" are
	 * available in the model this method will move them to the correct place if
	 * required. The movement can be influenced by a tag which begins with
	 * {@value #MOVE_TAG} followed by the normal positioning information (e.g.:
	 * move_after:PerspectiveSpacer). For more information about positioning have a
	 * look at: {@link PositionInfo#parse(String)}.
	 * </p>
	 */
	private void positionQuickAccess() {
		/*
		 * The QUICK_ACCESS_ELEMENT_IDS array contains the IDs of optional elements
		 * provided via an e4xmi application model fragment. The method checks if they
		 * should be moved to a special position. This behavior is required because
		 * nearly all elements in the legacy workbench are not provided via e4xmi
		 * application model. They are provided programmatically after the e4xmi
		 * application model and the corresponding fragment models are already
		 * processed.
		 */
		for (String quickAccessElementId : QUICK_ACCESS_ELEMENT_IDS) {
			MToolControl quickAccessElement = (MToolControl) modelService.find(quickAccessElementId, model);
			if (quickAccessElement != null) {
				moveControl(quickAccessElement.getParent(), quickAccessElement);

				// target the quick access field specifically
				if (QUICK_ACCESS_ID.equals(quickAccessElement.getElementId())) {
					if (model.getTags().contains(QUICK_ACCESS_HIDDEN)) {
						if (!quickAccessElement.getTags().contains(IPresentationEngine.HIDDEN_EXPLICITLY)) {
							quickAccessElement.getTags().add(IPresentationEngine.HIDDEN_EXPLICITLY);
						}
					} else if (!model.getTags().contains(QUICK_ACCESS_DEFAULT_VISIBILITY_CHANGED)
							&& hidesQuickAccessPerDefault()) {
						quickAccessElement.getTags().add(IPresentationEngine.HIDDEN_EXPLICITLY);
					}
				}
			}
		}

	}

	private static final String QUICK_ACCESS_ID = "SearchField"; //$NON-NLS-1$
	private static final String QUICK_ACCESS_HIDDEN = "QUICK_ACCESS_HIDDEN"; //$NON-NLS-1$
	private static final String QUICK_ACCESS_DEFAULT_VISIBILITY_CHANGED = "QUICK_ACCESS_DEFAULT_VISIBILITY_CHANGED"; //$NON-NLS-1$

	private static boolean hidesQuickAccessPerDefault() {
		IPreferenceStore preferenceStore = PlatformUI.getPreferenceStore();
		return preferenceStore.getBoolean(IWorkbenchPreferenceConstants.HIDE_QUICK_ACCESS_PER_DEFAULT);
	}

	@Inject
	private void hideQuickAccess(@Optional @UIEventTopic(UIEvents.ApplicationElement.TOPIC_TAGS) Event event) {
		if (event == null) {
			return;
		}
		Object origin = event.getProperty(UIEvents.EventTags.ELEMENT);
		if (!(origin instanceof MToolControl)) {
			return;
		}
		MToolControl control = (MToolControl) origin;
		if (!QUICK_ACCESS_ID.equals(control.getElementId())) {
			return;
		}
		MWindow myWindow = modelService.getTopLevelWindowFor(control);
		if (myWindow != model) {
			return;
		}
		if (UIEvents.isADD(event)) {
			if (UIEvents.contains(event, UIEvents.EventTags.NEW_VALUE, IPresentationEngine.HIDDEN_EXPLICITLY)) {
				if (!model.getTags().contains(QUICK_ACCESS_HIDDEN)) {
					model.getTags().add(QUICK_ACCESS_HIDDEN);
					quickAccessDefaultVisibilityChanged();
				}
			}
		} else if (UIEvents.isREMOVE(event)) {
			if (UIEvents.contains(event, UIEvents.EventTags.OLD_VALUE, IPresentationEngine.HIDDEN_EXPLICITLY)) {
				model.getTags().remove(QUICK_ACCESS_HIDDEN);
				quickAccessDefaultVisibilityChanged();
			}
		}
	}

	private void quickAccessDefaultVisibilityChanged() {
		model.getTags().add(QUICK_ACCESS_DEFAULT_VISIBILITY_CHANGED);
	}

	/**
	 * Moves the given element from its current position to the position mentioned
	 * in one of its tags.
	 *
	 * @param elementContainer the list of elements in which the element should be
	 *                         moved
	 * @param element          the element to move
	 */
	private void moveControl(MElementContainer<MUIElement> elementContainer, MUIElement element) {
		if (element == null || elementContainer == null)
			return;

		PositionInfo positionInfo = findMovePositionInfo(element);

		// does the element has a tag with a "move_" position info
		if (positionInfo != null) {
			List<MUIElement> elements = elementContainer.getChildren();

			if (elements.remove(element)) {
				// reposition only if the element was in the list

				switch (positionInfo.getPosition()) {
				case LAST:
					elements.add(element);
					break;

				case FIRST:
					elements.add(0, element);
					break;

				case INDEX:
					int index = positionInfo.getPositionReferenceAsInteger();
					if (index >= 0 && index < elements.size()) {
						elements.add(index, element);
					} else {
						elements.add(element);
					}
					break;

				case BEFORE:
				case AFTER:
					int idx = indexOfElementWithID(elements, positionInfo.getPositionReference());
					if (idx < 0) {
						// element no found
						elements.add(element);
					} else {
						if (positionInfo.getPosition() == Position.AFTER) {
							idx++;
						}

						if (idx < elements.size()) {
							elements.add(idx, element);
						} else {
							elements.add(element);
						}
					}
					break;

				default:
					WorkbenchPlugin.log("Can't position control '" + element.getElementId() //$NON-NLS-1$
							+ "' because of the unknown position type '" //$NON-NLS-1$
							+ positionInfo.getPosition() + "'!"); //$NON-NLS-1$
				}
			}
		}
	}

	/**
	 * Find the element with the given id in the given list of {@link MUIElement}s.
	 *
	 * @param elements the list of {@link MUIElement}s to search
	 * @param id       the id of the {@link MUIElement} to find
	 * @return the index of the {@link MUIElement} in the given list or -1 if
	 *         element wasn't found
	 */
	private int indexOfElementWithID(List<MUIElement> elements, String id) {
		if (elements == null || id == null)
			return -1;

		int index = 0;
		for (MUIElement element : elements) {
			if (id.equals(element.getElementId())) {
				return index;
			}
			index++;
		}

		return -1;
	}

	/**
	 * Checks if the {@link MUIElement} has a tag starting with {@value #MOVE_TAG}
	 * and if so it will extract the {@link PositionInfo} out of it.
	 *
	 * @param element the element to check
	 * @return the found {@link PositionInfo} on the given {@link MUIElement}, or
	 *         <code>null</code> if none was found
	 */
	private PositionInfo findMovePositionInfo(MUIElement element) {
		if (element != null) {
			for (String tag : element.getTags()) {
				if (tag.startsWith(MOVE_TAG)) {
					return PositionInfo.parse(tag.substring(MOVE_TAG.length()));
				}
			}
		}

		return null;
	}

	private void populateStandardTrim(MTrimBar bottomTrim) {
		// StatusLine
		MToolControl slElement = (MToolControl) modelService.find(STATUS_LINE_ID, model);
		if (slElement == null) {
			slElement = modelService.createModelElement(MToolControl.class);
			slElement.setElementId(STATUS_LINE_ID);
			slElement.setContributionURI(TRIM_CONTRIBUTION_URI);
			bottomTrim.getChildren().add(slElement);
		}
		slElement.setToBeRendered(statusLineVisible);
		slElement.getTags().add(TrimBarLayout.SPACER);

		// Heap Status
		MToolControl hsElement = (MToolControl) modelService.find("org.eclipse.ui.HeapStatus", model); //$NON-NLS-1$
		if (hsElement == null) {
			hsElement = modelService.createModelElement(MToolControl.class);
			hsElement.setElementId("org.eclipse.ui.HeapStatus"); //$NON-NLS-1$
			hsElement.setContributionURI(TRIM_CONTRIBUTION_URI);
			hsElement.getTags().add(IPresentationEngine.DRAGGABLE);
			bottomTrim.getChildren().add(hsElement);
		}
		hsElement.setToBeRendered(getShowHeapStatus());

		// Progress Bar
		MToolControl pbElement = (MToolControl) modelService.find("org.eclipse.ui.ProgressBar", model); //$NON-NLS-1$
		if (pbElement == null) {
			pbElement = modelService.createModelElement(MToolControl.class);
			pbElement.setElementId("org.eclipse.ui.ProgressBar"); //$NON-NLS-1$
			pbElement.getTags().add(IPresentationEngine.DRAGGABLE);
			pbElement.setContributionURI(TRIM_CONTRIBUTION_URI);
			bottomTrim.getChildren().add(pbElement);
		}
		pbElement.setToBeRendered(getWindowConfigurer().getShowProgressIndicator());
	}

	private void populateTrimContributions(MTrimBar bottomTrim) {
		// Part 1: Add groups
		IConfigurationElement[] exts = extensionRegistry.getConfigurationElementsFor("org.eclipse.ui.menus"); //$NON-NLS-1$
		List<IConfigurationElement> items = new ArrayList<>();
		for (IConfigurationElement ice : exts) {
			if ("group".equals(ice.getName()) || "widget".equals(ice.getName())) { //$NON-NLS-1$ //$NON-NLS-2$
				items.add(ice);
			}
		}

		if (items.isEmpty())
			return;

		// Iterate over the items until they've all been placed or until
		// an iteration doesn't place anything
		List<IConfigurationElement> handledElements = new ArrayList<>();
		handledElements.add(items.get(0)); // Hack!! startup seeding
		MUIElement createdTrim = null;
		while (items.size() > 0 && handledElements.size() > 0) {
			handledElements.clear();

			for (IConfigurationElement item : items) {
				String id = item.getAttribute("id"); //$NON-NLS-1$
				String classSpec = item.getAttribute("class"); //$NON-NLS-1$
				// boolean sepVisible = "true".equals(item.getAttribute("separatorsVisible"));
				// //$NON-NLS-1$ //$NON-NLS-2$
				IConfigurationElement[] locs = item.getChildren("location"); //$NON-NLS-1$
				for (IConfigurationElement loc : locs) {
					IConfigurationElement[] bars = loc.getChildren("bar"); //$NON-NLS-1$
					if (bars.length > 0) {
						IConfigurationElement bar = bars[0];
						boolean isTrim = "trim".equals(bar.getAttribute("type")); //$NON-NLS-1$//$NON-NLS-2$
						if (isTrim) {
							String path = bar.getAttribute("path"); //$NON-NLS-1$
							if (path != null && path.length() > 0) {
								createdTrim = addTrimElement(bottomTrim, item, id, false, path, classSpec);
							} else {
								IConfigurationElement[] orders = loc.getChildren("order"); //$NON-NLS-1$
								if (orders.length > 0) {
									boolean isBefore = "before".equals(orders[0].getAttribute("position")); //$NON-NLS-1$//$NON-NLS-2$
									String relTo = orders[0].getAttribute("relativeTo"); //$NON-NLS-1$
									if ("status".equals(relTo)) //$NON-NLS-1$
										relTo = STATUS_LINE_ID;

									createdTrim = addTrimElement(bottomTrim, item, id, isBefore, relTo, classSpec);
								}
							}

							if (createdTrim != null) {
								handledElements.add(item);
							}
						}
					}
				}
			}

			items.removeAll(handledElements);
		}
	}

	private MToolControl addTrimElement(MTrimBar bottomTrim, IConfigurationElement ice, String id, boolean isBefore,
			String relTo, String classSpec) {
		// is it already in the trim ?
		MUIElement existingTrim = modelService.find(id, bottomTrim);
		if (existingTrim != null) {
			iceMap.put((MToolControl) existingTrim, ice);
			return (MToolControl) existingTrim;
		}

		// Ok, create one but only if we can site it correctly
		int insertIndex = bottomTrim.getChildren().size();
		if (relTo != null) {
			MUIElement foundRel = modelService.find(relTo, bottomTrim);
			if (foundRel == null)
				return null;
			insertIndex = bottomTrim.getChildren().indexOf(foundRel);
			if (!isBefore)
				insertIndex++;
		}

		MToolControl newTrimElement = modelService.createModelElement(MToolControl.class);
		newTrimElement.setElementId(id);
		newTrimElement.setToBeRendered(classSpec != null);
		if (classSpec != null) {
			newTrimElement
					.setContributionURI("bundleclass://org.eclipse.ui.workbench/org.eclipse.ui.internal.LegacyTrim"); //$NON-NLS-1$
		}
		newTrimElement.setContributorURI(URIHelper.constructPlatformURI(ice.getContributor()));

		iceMap.put(newTrimElement, ice);
		bottomTrim.getChildren().add(insertIndex, newTrimElement);

		return newTrimElement;
	}

	void populateBottomTrimContributions() {
		MTrimBar bottomTrim = modelService.getTrim(model, SideValue.BOTTOM);

		populateStandardTrim(bottomTrim);
		populateTrimContributions(bottomTrim);
	}

	public MTrimBar getTopTrim() {
		List<MTrimBar> trimBars = model.getTrimBars();
		for (MTrimBar bar : trimBars) {
			if (IWorkbenchConstants.MAIN_TOOLBAR_ID.equals(bar.getElementId())) {
				return bar;
			}
		}
		return null;
	}

	public static String getId(IConfigurationElement element) {
		String id = element.getAttribute(IWorkbenchRegistryConstants.ATT_ID);

		// For sub-menu management -all- items must be id'd so enforce this
		// here (we could optimize by checking the 'name' of the config
		// element == "menu"
		if (id == null || id.isEmpty()) {
			id = getCommandId(element);
		}
		if (id == null || id.isEmpty()) {
			id = element.toString();
		}

		return id;
	}

	public static String getCommandId(IConfigurationElement element) {
		return element.getAttribute(IWorkbenchRegistryConstants.ATT_COMMAND_ID);
	}

	public static String getActionSetCommandId(IConfigurationElement element) {
		String id = getDefinitionId(element);
		if (id != null) {
			return id;
		}
		id = getId(element);
		String actionSetId = null;
		Object obj = element.getParent();
		while (obj instanceof IConfigurationElement && actionSetId == null) {
			IConfigurationElement parent = (IConfigurationElement) obj;
			if (parent.getName().equals(IWorkbenchRegistryConstants.TAG_ACTION_SET)) {
				actionSetId = getId(parent);
			}
			obj = parent.getParent();
		}
		return ACTION_SET_CMD_PREFIX + actionSetId + '/' + id;
	}

	public static String getDefinitionId(IConfigurationElement element) {
		return element.getAttribute(IWorkbenchRegistryConstants.ATT_DEFINITION_ID);
	}

	public static boolean getRetarget(IConfigurationElement element) {
		String r = element.getAttribute(IWorkbenchRegistryConstants.ATT_RETARGET);
		return Boolean.parseBoolean(r);
	}

	/**
	 * Return the style bits for the shortcut bar.
	 *
	 * @return int
	 */
	protected int perspectiveBarStyle() {
		return SWT.FLAT | SWT.WRAP | SWT.RIGHT | SWT.HORIZONTAL;
	}

	private boolean coolBarVisible = true;

	private boolean perspectiveBarVisible = true;

	private boolean statusLineVisible = true;

	/**
	 * The handlers for global actions that were last submitted to the workbench
	 * command support. This is a map of command identifiers to
	 * <code>ActionHandler</code>. This map is never <code>null</code>, and is never
	 * empty as long as at least one global action has been registered.
	 */
	private Map<String, ActionHandler> globalActionHandlersByCommandId = new HashMap<>();

	/**
	 * The list of handler submissions submitted to the workbench command support.
	 * This list may be empty, but it is never <code>null</code>.
	 */
	private List<IHandlerActivation> handlerActivations = new ArrayList<>();

	/**
	 * The number of large updates that are currently going on. If this is number is
	 * greater than zero, then UI updateActionBars is a no-op.
	 *
	 * @since 3.1
	 */
	private int largeUpdates = 0;

	private IExtensionTracker tracker;

	private void firePageClosed() {
		pageListeners.firePageClosed(page);
	}

	private void firePageOpened() {
		pageListeners.firePageOpened(page);
	}

	private void firePageActivated() {
		pageListeners.firePageActivated(page);
	}

	void registerGlobalAction(IAction globalAction) {
		String commandId = globalAction.getActionDefinitionId();

		if (commandId != null) {
			final Object value = globalActionHandlersByCommandId.remove(commandId);
			if (value instanceof ActionHandler) {
				// This handler is about to get clobbered, so dispose it.
				final ActionHandler handler = (ActionHandler) value;
				handler.dispose();
			}

			if (globalAction instanceof CommandAction) {
				final String actionId = globalAction.getId();
				if (actionId != null) {
					final IActionCommandMappingService mappingService = serviceLocator
							.getService(IActionCommandMappingService.class);
					mappingService.map(actionId, commandId);
				}
			} else {
				globalActionHandlersByCommandId.put(commandId, new ActionHandler(globalAction));
			}
		}

		submitGlobalActions();
	}

	/**
	 * <p>
	 * Submits the action handlers for action set actions and global actions. Global
	 * actions are given priority, so that if a global action and an action set
	 * action both handle the same command, the global action is given priority.
	 * </p>
	 * <p>
	 * These submissions are submitted as <code>Priority.LEGACY</code>, which means
	 * that they are the lowest priority. This means that if a higher priority
	 * submission handles the same command under the same conditions, that that
	 * submission will become the handler.
	 * </p>
	 */
	void submitGlobalActions() {
		final IHandlerService handlerService = getService(IHandlerService.class);

		/*
		 * Mash the action sets and global actions together, with global actions taking
		 * priority.
		 */
		Map<String, ActionHandler> handlersByCommandId = new HashMap<>();
		handlersByCommandId.putAll(globalActionHandlersByCommandId);

		List<IHandlerActivation> newHandlers = new ArrayList<>(handlersByCommandId.size());

		Iterator<IHandlerActivation> existingIter = handlerActivations.iterator();
		while (existingIter.hasNext()) {
			IHandlerActivation next = existingIter.next();

			String cmdId = next.getCommandId();

			Object handler = handlersByCommandId.get(cmdId);
			if (handler == next.getHandler()) {
				handlersByCommandId.remove(cmdId);
				newHandlers.add(next);
			} else {
				handlerService.deactivateHandler(next);
			}
		}

		final Shell shell = getShell();
		if (shell != null) {
			final Expression expression = new ActiveShellExpression(shell);
			for (Entry<String, ActionHandler> entry : handlersByCommandId.entrySet()) {
				String commandId = entry.getKey();
				IHandler handler = entry.getValue();
				newHandlers.add(handlerService.activateHandler(commandId, handler, expression));
			}
		}

		handlerActivations = newHandlers;
	}

	/**
	 * Add a generic property listener.
	 *
	 * @param listener the listener to add
	 * @since 3.3
	 */
	public void addPropertyChangeListener(IPropertyChangeListener listener) {
		genericPropertyListeners.add(listener);
	}

	/**
	 * Removes a generic property listener.
	 *
	 * @param listener the listener to remove
	 * @since 3.3
	 */
	public void removePropertyChangeListener(IPropertyChangeListener listener) {
		genericPropertyListeners.remove(listener);
	}

	private void firePropertyChanged(final String property, final Object oldValue, final Object newValue) {
		PropertyChangeEvent event = new PropertyChangeEvent(this, property, oldValue, newValue);
		for (Object listener : genericPropertyListeners.getListeners()) {
			IPropertyChangeListener propertyChangeListener = (IPropertyChangeListener) listener;
			propertyChangeListener.propertyChange(event);
		}
	}

	/*
	 * Adds an listener to the part service.
	 */
	@Override
	public void addPageListener(IPageListener l) {
		pageListeners.addPageListener(l);
	}

	/**
	 * @see org.eclipse.ui.IPageService
	 */
	@Override
	public void addPerspectiveListener(org.eclipse.ui.IPerspectiveListener l) {
		perspectiveListeners.addPerspectiveListener(l);
	}

	/**
	 * Close the window.
	 *
	 * Assumes that busy cursor is active.
	 */
	private boolean busyClose(boolean remove) {
		/*
		 * Warning: Intricate flow of control and re-entrant invocations of this method:
		 *
		 * - busyClose(true) is called from WorkbenchWindow#close() when the user closes
		 * a workbench window.
		 *
		 * - busyClose(false) is called from Workbench#close(int, boolean). This happens
		 * on File > Exit/Restart, [Mac] Quit Eclipse, AND ... tadaa ... from
		 * busyClose(true) when the user closes the last window => [Case A]
		 *
		 * Additional complication: busyClose(true) can also be called again when
		 * someone runs an event loop during the shutdown sequence. In that case, the
		 * nested busyClose(true) should be dropped (bug 381555) => [Case B]
		 */
		if (closing) {
			// [Case A] Window is already closing.
			return false;
		}
		if (updateDisabled && remove) {
			// [Case B] User closed this window, which triggered
			// "workbench.close()", during which the user tried to close this
			// window again.
			return false;
		}

		// Whether the window was actually closed or not
		boolean windowClosed = false;

		// Setup internal flags to indicate window is in
		// progress of closing and no update should be done.
		updateDisabled = true;

		try {
			// Tag the currently active part so we can restore focus on startup
			IWorkbenchPage activePage = getActivePage();
			if (activePage != null) {
				WorkbenchPartReference ref = (WorkbenchPartReference) activePage.getActivePartReference();
				if (ref != null) {
					ref.getModel().getTags().add(EPartService.ACTIVE_ON_CLOSE_TAG);
				}
			}

			// Only do the check if it is OK to close if we are not closing
			// via the workbench as the workbench will check this itself.
			Workbench workbench = getWorkbenchImpl();
			int count = workbench.getWorkbenchWindowCount();
			// also check for starting - if the first window dies on startup
			// then we'll need to open a default window.
			if (!workbench.isStarting() && !workbench.isClosing() && count <= 1
					&& workbench.getWorkbenchConfigurer().getExitOnLastWindowClose()) {
				windowClosed = workbench.close();
			} else if (okToClose()) {
				closing = true;
				windowClosed = hardClose(remove);
			}
		} finally {
			if (!windowClosed) {
				// Reset the internal flags if window was not closed.
				closing = false;
				updateDisabled = false;
			}
		}

		if (windowClosed && tracker != null) {
			tracker.close();
		}

		return windowClosed;
	}

	@Override
	public Shell getShell() {
		return (Shell) model.getWidget();
	}

	public boolean close(final boolean remove) {
		final boolean[] ret = new boolean[1];
		BusyIndicator.showWhile(null, () -> ret[0] = busyClose(remove));
		return ret[0];
	}

	/**
	 * @see IWorkbenchWindow
	 */
	@Override
	public boolean close() {
		return close(true);
	}

	@Override
	public boolean isClosing() {
		return closing || getWorkbenchImpl().isClosing();
	}

	/**
	 * Notifies interested parties (namely the advisor) that the window is about to
	 * be opened.
	 *
	 * @since 3.1
	 */
	private void fireWindowOpening() {
		// let the application do further configuration
		getWindowAdvisor().preWindowOpen();
	}

	void fireWindowOpened() {
		// notify the advisor
		getWindowAdvisor().postWindowOpen();
	}

	/**
	 * Notifies interested parties (namely the advisor) that the window has been
	 * restored from a previously saved state.
	 *
	 * @throws WorkbenchException passed through from the advisor
	 * @since 3.1
	 */
	void fireWindowRestored() throws WorkbenchException {
		StartupThreading.runWithWorkbenchExceptions(new StartupRunnable() {
			@Override
			public void runWithException() throws Throwable {
				getWindowAdvisor().postWindowRestore();
			}
		});
	}

	/**
	 * Notifies interested parties (namely the advisor and the window listeners)
	 * that the window has been closed.
	 *
	 * @since 3.1
	 */
	private void fireWindowClosed() {
		// let the application do further deconfiguration
		getWindowAdvisor().postWindowClose();
		getWorkbenchImpl().fireWindowClosed(this);
	}

	/**
	 * Mark contributions dirty for future update.
	 */
	private void allowUpdates(IMenuManager menuManager) {
		menuManager.markDirty();
		for (IContributionItem item : menuManager.getItems()) {
			if (item instanceof IMenuManager) {
				allowUpdates((IMenuManager) item);
			} else if (item instanceof SubContributionItem) {
				final IContributionItem innerItem = ((SubContributionItem) item).getInnerItem();
				if (innerItem instanceof IMenuManager) {
					allowUpdates((IMenuManager) innerItem);
				}
			}
		}
	}

	/**
	 * Fires perspective activated
	 */
	void firePerspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
		IMenuManager windowManager = ((WorkbenchPage) page).getActionBars().getMenuManager();
		allowUpdates(windowManager);
		windowManager.update(false);

		UIListenerLogging.logPerspectiveEvent(this, page, perspective, UIListenerLogging.PLE_PERSP_ACTIVATED);
		perspectiveListeners.firePerspectiveActivated(page, perspective);
	}

	/**
	 * Fires perspective deactivated.
	 *
	 * @since 3.2
	 */
	void firePerspectivePreDeactivate(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
		UIListenerLogging.logPerspectiveEvent(this, page, perspective, UIListenerLogging.PLE_PERSP_PRE_DEACTIVATE);
		perspectiveListeners.firePerspectivePreDeactivate(page, perspective);
	}

	/**
	 * Fires perspective deactivated.
	 *
	 * @since 3.1
	 */
	void firePerspectiveDeactivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
		UIListenerLogging.logPerspectiveEvent(this, page, perspective, UIListenerLogging.PLE_PERSP_DEACTIVATED);
		perspectiveListeners.firePerspectiveDeactivated(page, perspective);
	}

	/**
	 * Fires perspective changed
	 *
	 * @param page
	 * @param perspective
	 * @param changeId
	 */
	public void firePerspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, String changeId) {
		// Some callers call this even when there is no active perspective.
		// Just ignore this case.
		if (perspective != null) {
			UIListenerLogging.logPerspectiveChangedEvent(this, page, perspective, null, changeId);
			perspectiveListeners.firePerspectiveChanged(page, perspective, changeId);
		}
	}

	/**
	 * Fires perspective changed for an affected part
	 *
	 * @param page
	 * @param perspective
	 * @param partRef
	 * @param changeId
	 */
	public void firePerspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective,
			IWorkbenchPartReference partRef, String changeId) {
		// Some callers call this even when there is no active perspective.
		// Just ignore this case.
		if (perspective != null) {
			UIListenerLogging.logPerspectiveChangedEvent(this, page, perspective, partRef, changeId);
			perspectiveListeners.firePerspectiveChanged(page, perspective, partRef, changeId);
		}
	}

	/**
	 * Fires perspective closed
	 */
	void firePerspectiveClosed(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
		UIListenerLogging.logPerspectiveEvent(this, page, perspective, UIListenerLogging.PLE_PERSP_CLOSED);
		perspectiveListeners.firePerspectiveClosed(page, perspective);
	}

	/**
	 * Fires perspective opened
	 */
	void firePerspectiveOpened(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
		UIListenerLogging.logPerspectiveEvent(this, page, perspective, UIListenerLogging.PLE_PERSP_OPENED);
		perspectiveListeners.firePerspectiveOpened(page, perspective);
	}

	/**
	 * Fires perspective saved as.
	 *
	 * @since 3.1
	 */
	void firePerspectiveSavedAs(IWorkbenchPage page, IPerspectiveDescriptor oldPerspective,
			IPerspectiveDescriptor newPerspective) {
		UIListenerLogging.logPerspectiveSavedAs(this, page, oldPerspective, newPerspective);
		perspectiveListeners.firePerspectiveSavedAs(page, oldPerspective, newPerspective);
	}

	/**
	 * Returns the action bars for this window.
	 *
	 * @return this window's action bars
	 */
	public WWinActionBars getActionBars() {
		if (actionBars == null) {
			actionBars = new WWinActionBars(this);
		}
		return actionBars;
	}

	@Override
	public IWorkbenchPage getActivePage() {
		return page;
	}

	@Override
	public IWorkbenchPage[] getPages() {
		return page == null ? new IWorkbenchPage[0] : new IWorkbenchPage[] { page };
	}

	/**
	 * @see IWorkbenchWindow
	 */
	@Override
	public IPartService getPartService() {
		return partService;
	}

	/**
	 * Returns the layout for the shell.
	 *
	 * @return the layout for the shell
	 */
	protected Layout getLayout() {
		return null;
	}

	/**
	 * @see IWorkbenchWindow
	 */
	@Override
	public ISelectionService getSelectionService() {
		return selectionService;
	}

	/**
	 * Returns <code>true</code> when the window's shell is activated,
	 * <code>false</code> when it's shell is deactivated
	 *
	 * @return boolean <code>true</code> when shell activated, <code>false</code>
	 *         when shell deactivated
	 */
	public boolean getShellActivated() {
		return shellActivated;
	}

	/**
	 * @see IWorkbenchWindow
	 */
	@Override
	public IWorkbench getWorkbench() {
		return PlatformUI.getWorkbench();
	}

	private void hideNonRestorableViews() {
		List<MPart> sharedPartsToRemove = new ArrayList<>();
		List<MPlaceholder> phList = modelService.findElements(model, null, MPlaceholder.class, null);
		for (MPlaceholder ph : phList) {
			if (!(ph.getRef() instanceof MPart))
				continue;

			String partId = ph.getElementId();

			// If the id contains a ':' use the part before it as the
			// descriptor id
			int colonIndex = partId.indexOf(':');
			String descId = colonIndex == -1 ? partId : partId.substring(0, colonIndex);
			String secondaryId = colonIndex == -1 ? null : partId.substring(colonIndex + 1);
			IViewDescriptor regEntry = ((Workbench) workbench).getViewRegistry().find(descId);
			if (regEntry != null && !regEntry.isRestorable() && !("*".equals(secondaryId))) { //$NON-NLS-1$
				MElementContainer<MUIElement> phParent = ph.getParent();
				if (colonIndex != -1) {
					// if it's a multi-instance part remove it (and its MPart)
					if (!sharedPartsToRemove.contains(ph.getRef()))
						sharedPartsToRemove.add((MPart) ph.getRef());
					ph.getParent().getChildren().remove(ph);
				} else if (ph.isToBeRendered()) {
					// just hide it (so we remember where to open it again
					ph.setToBeRendered(false);
				}

				// We need to do our own cleanup here...
				int vc = modelService.countRenderableChildren(phParent);
				if (vc == 0) {
					if (!isLastEditorStack(phParent))
						phParent.setToBeRendered(false);
				}
			}
		}

		// Remove the actual shared Parts for any placeholder that was removed
		List<MUIElement> seList = model.getSharedElements();
		for (MPart partToRemove : sharedPartsToRemove) {
			seList.remove(partToRemove);
		}
	}

	private boolean isLastEditorStack(MUIElement element) {
		return modelService.isLastEditorStack(element);
	}

	/**
	 * Unconditionally close this window. Assumes the proper flags have been set
	 * correctly (e.i. closing and updateDisabled)
	 *
	 * @param remove <code>true</code> if this window should be removed from the
	 *               application model
	 */
	private boolean hardClose(boolean remove) {
		try {
			if (!remove) {
				// we're in a shutdown case so we need to hide views that should
				// not be restored
				hideNonRestorableViews();
			}

			// clear some lables
			// Remove the handler submissions. Bug 64024.
			final IWorkbench workbench = getWorkbench();
			LegacyHandlerService windowHs = (LegacyHandlerService) model.getContext().get(IHandlerService.class);
			windowHs.dispose();
			final IHandlerService handlerService = workbench.getService(IHandlerService.class);
			handlerService.deactivateHandlers(handlerActivations);
			final Iterator<IHandlerActivation> activationItr = handlerActivations.iterator();
			while (activationItr.hasNext()) {
				final IHandlerActivation activation = activationItr.next();
				activation.getHandler().dispose();
			}
			handlerActivations.clear();
			globalActionHandlersByCommandId.clear();

			// Remove the enabled submissions. Bug 64024.
			final IContextService contextService = workbench.getService(IContextService.class);
			contextService.unregisterShell(getShell());

			// time to wipe our our populate
			// IMenuService menuService = (IMenuService)
			// workbench.getService(IMenuService.class);
			// menuService.releaseContributions(((ContributionManager)
			// getActionBars()
			// .getMenuManager()));
			// ICoolBarManager coolbar = getActionBars().getCoolBarManager();
			// if (coolbar != null) {
			// menuService.releaseContributions(((ContributionManager)
			// coolbar));
			// }

			getActionBarAdvisor().dispose();
			getWindowAdvisor().dispose();

			// Null out the progress region. Bug 64024.
			progressRegion = null;

			// Opposite of setup() and fill()
			MWindow window = model;
			if (window.getMainMenu() != null) {
				MMenu mainMenu = window.getMainMenu();
				final MenuManagerRenderer renderer = (MenuManagerRenderer) rendererFactory.getRenderer(mainMenu, null);
				cleanupMenuManagerRec(renderer, mainMenu);
			}

			engine.removeGui(model);
			coolbarToTrim.dispose();

			MElementContainer<MUIElement> parent = window.getParent();
			if (remove) {
				parent.getChildren().remove(window);

				if (parent.getSelectedElement() == window) {
					if (!parent.getChildren().isEmpty()) {
						parent.setSelectedElement(parent.getChildren().get(0));
					}
				}
			}
			// We fire "page closed" *before* closing the page for compatibility reasons:
			// since we never really closed the page, the clients expect that page
			// is fully functional during this call
			if (getActivePage() != null) {
				firePageClosed();
			}
			// now it is safe to close the page and release all references
			if (page != null) {
				page.close();
				page = null;
			}
			menuOverride = null;
			toolbarOverride = null;
			fireWindowClosed();
		} finally {

			try {
				// Bring down all of the services ... after the window goes away
				serviceLocator.dispose();
			} catch (Exception ex) {
				WorkbenchPlugin.log(ex);
			}
			menuRestrictions.clear();
		}
		return true;
	}

	private void cleanupMenuManagerRec(MenuManagerRenderer renderer, MMenu m) {
		for (MMenuElement e : m.getChildren()) {
			// renderer.clearModelToContribution(e, null);
			if (e instanceof MMenu) {
				cleanupMenuManagerRec(renderer, (MMenu) e);
			}
		}
		renderer.clearModelToManager(m, null);
	}

	/**
	 * @see IWorkbenchWindow
	 */
	@Override
	public boolean isApplicationMenu(String menuID) {
		// delegate this question to the action bar advisor
		return getActionBarAdvisor().isApplicationMenu(menuID);
	}

	boolean isWorkbenchCoolItemId(String id) {
		return windowConfigurer.containsCoolItem(id);
	}

	/**
	 * Called when this window is about to be closed.
	 */
	private boolean okToClose() {
		if (!getWorkbenchImpl().isClosing()) {
			return saveAllParts(true, true, true);
		}
		return true;
	}

	private boolean saveAllParts(boolean confirm, boolean closing, boolean addNonPartSources) {
		if (modelService != null) {
			Set<MPart> dirtyParts = new HashSet<>();
			final IEclipseContext context = model.getContext();
			if (context != null) {
				EPartService partService = context.get(EPartService.class);
				if (partService != null) {
					Collection<MPart> parts = null;
					try {
						parts = partService.getDirtyParts();
						dirtyParts.addAll(parts);
					} catch (IllegalStateException e) {
						// This is to handle the case if the partService is instance of
						// ApplicationPartServiceImpl and does not have an active window
						// do nothing
					}
				}
				if (dirtyParts != null && dirtyParts.size() > 0) {
					ISaveHandler saveHandler = context.get(ISaveHandler.class);
					if (saveHandler != null) {
						if (saveHandler instanceof WWinPartServiceSaveHandler) {
							try {
								return ((WWinPartServiceSaveHandler) saveHandler).saveParts(dirtyParts, confirm,
										closing, addNonPartSources);
							} catch (UnsupportedOperationException e) {
								// do nothing
							}
						}
					}
				}
			}
		}
		// Save all of the editors.
		if (!getWorkbenchImpl().isClosing()) {
			IWorkbenchPage page = getActivePage();
			if (page != null) {
				return ((WorkbenchPage) page).saveAllEditors(true, true, true);
			}
		}
		return true;
	}

	@Override
	public IWorkbenchPage openPage(final String perspectiveId, final IAdaptable input) throws WorkbenchException {
		final Object[] result = new Object[1];
		BusyIndicator.showWhile(null, () -> {
			try {
				result[0] = busyOpenPage(perspectiveId, input);
			} catch (WorkbenchException e) {
				result[0] = e;
			}
		});

		if (result[0] instanceof IWorkbenchPage) {
			return (IWorkbenchPage) result[0];
		} else if (result[0] instanceof WorkbenchException) {
			throw (WorkbenchException) result[0];
		} else {
			throw new WorkbenchException(WorkbenchMessages.WorkbenchWindow_exceptionMessage);
		}
	}

	private IWorkbenchPage busyOpenPage(String perspectiveId, IAdaptable input) throws WorkbenchException {
		IPerspectiveDescriptor descriptor = workbench.getPerspectiveRegistry().findPerspectiveWithId(perspectiveId);
		if (descriptor == null) {
			throw new WorkbenchException(
					NLS.bind(WorkbenchMessages.WorkbenchPage_ErrorCreatingPerspective, perspectiveId));
		}

		if (page == null) {
			page = new WorkbenchPage(this, input);
			model.getContext().set(IWorkbenchPage.class.getName(), page);

			try {
				ContextInjectionFactory.inject(page, model.getContext());
			} catch (InjectionException e) {
				throw new WorkbenchException(e.getMessage(), e);
			}

			firePageOpened();

			partService.setPage(page);
		} else {
			IWorkbenchWindow window = getWorkbench().openWorkbenchWindow(perspectiveId, input);
			return window.getActivePage();
		}

		perspective = descriptor;
		page.setPerspective(perspective);
		firePageActivated();

		return page;
	}

	@Override
	public IWorkbenchPage openPage(IAdaptable input) throws WorkbenchException {
		return openPage(workbench.getPerspectiveRegistry().getDefaultPerspective(), input);
	}

	/*
	 * Removes an listener from the part service.
	 */
	@Override
	public void removePageListener(IPageListener l) {
		pageListeners.removePageListener(l);
	}

	/**
	 * @see org.eclipse.ui.IPageService
	 */
	@Override
	public void removePerspectiveListener(org.eclipse.ui.IPerspectiveListener l) {
		perspectiveListeners.removePerspectiveListener(l);
	}

	private void disableControl(Control ctrl, List<Control> toEnable) {
		if (ctrl != null && !ctrl.isDisposed() && ctrl.isEnabled()) {
			ctrl.setEnabled(false);
			toEnable.add(ctrl);
		}
	}

	@Override
	public void run(final boolean fork, boolean cancelable, final IRunnableWithProgress runnable)
			throws InvocationTargetException, InterruptedException {
		final StatusLineManager manager = getStatusLineManager();

		// Temporary Hack for bug 330106, remove when bug 334093 is fixed
		boolean progressHack = manager.getControl() == null;
		if (manager == null || progressHack) {
			runnable.run(new NullProgressMonitor());
		} else {
			EPartService partService = model.getContext().get(EPartService.class);
			final MPart curActive = partService.getActivePart();
			boolean wasCancelEnabled = manager.isCancelEnabled();
			boolean enableMainMenu = false;

			IBindingService bs = model.getContext().get(IBindingService.class);
			boolean keyFilterEnabled = bs.isKeyFilterEnabled();
			List<Control> toEnable = new ArrayList<>();
			Shell theShell = getShell();
			Display display = theShell.getDisplay();
			Control currentFocus = display.getFocusControl();

			try {
				Menu mainMenu = (Menu) model.getMainMenu().getWidget();
				if (mainMenu != null && !mainMenu.isDisposed() && mainMenu.isEnabled()) {
					mainMenu.setEnabled(false);
					enableMainMenu = true;
				}

				if (keyFilterEnabled)
					bs.setKeyFilterEnabled(false);

				// disable all other shells
				for (Shell childShell : display.getShells()) {
					if (childShell != theShell) {
						disableControl(childShell, toEnable);
					}
				}

				// Disable the presentation (except the bottom trim)
				TrimmedPartLayout tpl = (TrimmedPartLayout) getShell().getLayout();
				disableControl(tpl.clientArea, toEnable);
				disableControl(tpl.top, toEnable);
				disableControl(tpl.left, toEnable);
				disableControl(tpl.right, toEnable);

				// Disable everything in the bottom trim except the status line
				if (tpl.bottom != null && !tpl.bottom.isDisposed() && tpl.bottom.isEnabled()) {
					MUIElement statusLine = modelService.find(STATUS_LINE_ID, model);
					Object slCtrl = statusLine != null ? statusLine.getWidget() : null;
					for (Control bottomCtrl : tpl.bottom.getChildren()) {
						if (bottomCtrl != slCtrl)
							disableControl(bottomCtrl, toEnable);
					}
				}

				manager.setCancelEnabled(cancelable);

				final InvocationTargetException[] ite = new InvocationTargetException[1];
				final InterruptedException[] ie = new InterruptedException[1];

				BusyIndicator.showWhile(getShell().getDisplay(), () -> {
					try {
						ModalContext.run(runnable, fork, manager.getProgressMonitor(), getShell().getDisplay());
					} catch (InvocationTargetException e1) {
						ite[0] = e1;
					} catch (InterruptedException e2) {
						ie[0] = e2;
					} finally {
						manager.getProgressMonitor().done();
					}
				});

				if (ite[0] != null) {
					throw ite[0];
				} else if (ie[0] != null) {
					throw ie[0];
				}
			} finally {
				manager.setCancelEnabled(wasCancelEnabled);

				// re-enable the main menu if necessary
				if (enableMainMenu && model != null && model.getMainMenu() != null) {
					Menu mainMenu = (Menu) model.getMainMenu().getWidget();
					mainMenu.setEnabled(true);
				}

				if (keyFilterEnabled)
					bs.setKeyFilterEnabled(true);

				// Re-enable any disabled controls
				for (Control ctrl : toEnable) {
					if (!ctrl.isDisposed() && !ctrl.isEnabled())
						ctrl.setEnabled(true);
				}

				MPart activePart = partService.getActivePart();
				if (curActive != activePart && activePart != null) {
					engine.focusGui(activePart);
				} else if (currentFocus != null && !currentFocus.isDisposed()) {
					// It's necessary to restore focus after reenabling the
					// controls
					// because disabling them causes focus to jump elsewhere.
					// Use forceFocus rather than setFocus to avoid SWT's
					// search for children which can take focus, so focus
					// ends up back on the actual control that previously had
					// it.
					currentFocus.forceFocus();
				}
			}
		}
	}

	@Override
	public void setActivePage(final IWorkbenchPage in) {
		if (getActivePage() != in) {
			if (in == null) {
				firePageClosed();
			}

			page = (WorkbenchPage) in;
			model.getContext().set(IWorkbenchPage.class, page);
			partService.setPage(page);
			updateActionSets();
			// submitGlobalActions();
		}
	}

	private Set<Object> menuRestrictions = new HashSet<>();

	private Boolean valueOf(boolean result) {
		return result ? Boolean.TRUE : Boolean.FALSE;
	}

	public Set<Object> getMenuRestrictions() {
		return menuRestrictions;
	}

	void liftRestrictions() {
		if (menuRestrictions.isEmpty()) {
			return;
		}
		EvaluationReference[] refs = menuRestrictions.toArray(new EvaluationReference[menuRestrictions.size()]);
		IEvaluationService es = serviceLocator.getService(IEvaluationService.class);
		IEvaluationContext currentState = es.getCurrentState();
		for (EvaluationReference reference : refs) {
			reference.setPostingChanges(true);

			boolean os = reference.evaluate(currentState);
			reference.clearResult();
			boolean ns = reference.evaluate(currentState);
			if (os != ns) {
				reference.getListener().propertyChange(
						new PropertyChangeEvent(reference, reference.getProperty(), valueOf(os), valueOf(ns)));
			}
		}
	}

	void imposeRestrictions() {
		Iterator<?> i = menuRestrictions.iterator();
		while (i.hasNext()) {
			EvaluationReference ref = (EvaluationReference) i.next();
			ref.setPostingChanges(false);
		}
	}

	/**
	 * Hooks a listener to track the activation and deactivation of the window's
	 * shell.
	 */
	private void trackShellActivation() {
		getShell().addShellListener(new ShellAdapter() {
			@Override
			public void shellActivated(ShellEvent event) {
				shellActivated = true;
				serviceLocator.activate();
				if (getActivePage() != null) {
					getWorkbenchImpl().fireWindowActivated(WorkbenchWindow.this);
				}
				liftRestrictions();
			}

			@Override
			public void shellDeactivated(ShellEvent event) {
				shellActivated = false;
				imposeRestrictions();
				serviceLocator.deactivate();
				if (getActivePage() != null) {
					getWorkbenchImpl().fireWindowDeactivated(WorkbenchWindow.this);
				}
			}
		});
	}

	/**
	 * update the action bars.
	 */
	public void updateActionBars() {
		if (getShell() == null || getShell().isDisposed() || updateDisabled || updatesDeferred()) {
			return;
		}

		if (mainMenu != null) {
			renderer.reconcileManagerToModel(menuManager, mainMenu);
		}

		try {
			getShell().setLayoutDeferred(true);
			eventBroker.send(UIEvents.REQUEST_ENABLEMENT_UPDATE_TOPIC, UIEvents.ALL_ELEMENT_ID);
			getCoolBarManager2().update(false);
		} finally {
			getShell().setLayoutDeferred(false);
		}

		getStatusLineManager().update(false);
	}

	/**
	 * Returns true if we are currently deferring UI processing due to a large
	 * update
	 *
	 * @return true if we are deferring UI updates.
	 * @since 3.1
	 */
	private boolean updatesDeferred() {
		return largeUpdates > 0;
	}

	/**
	 * <p>
	 * Indicates the start of a large update within this window. This is used to
	 * disable CPU-intensive, change-sensitive services that were temporarily
	 * disabled in the midst of large changes. This method should always be called
	 * in tandem with <code>largeUpdateEnd</code>, and the event loop should not be
	 * allowed to spin before that method is called.
	 * </p>
	 * <p>
	 * Important: always use with <code>largeUpdateEnd</code>!
	 * </p>
	 *
	 * @since 3.1
	 */
	public final void largeUpdateStart() {
		largeUpdates++;
	}

	/**
	 * <p>
	 * Indicates the end of a large update within this window. This is used to
	 * re-enable services that were temporarily disabled in the midst of large
	 * changes. This method should always be called in tandem with
	 * <code>largeUpdateStart</code>, and the event loop should not be allowed to
	 * spin before this method is called.
	 * </p>
	 * <p>
	 * Important: always protect this call by using <code>finally</code>!
	 * </p>
	 *
	 * @since 3.1
	 */
	public final void largeUpdateEnd() {
		if (--largeUpdates == 0) {
			updateActionBars();
		}
	}

	/**
	 * Update the visible action sets. This method is typically called from a page
	 * when the user changes the visible action sets within the prespective.
	 */
	public void updateActionSets() {
		if (updateDisabled) {
			return;
		}

		WorkbenchPage currentPage = (WorkbenchPage) getActivePage();
		if (currentPage == null) {
			getActionPresentation().clearActionSets();
		} else {
			ICoolBarManager2 coolBarManager = (ICoolBarManager2) getCoolBarManager2();
			if (coolBarManager != null) {
				coolBarManager.refresh();
			}
			getActionPresentation().setActionSets(currentPage.getActionSets());
		}
		fireActionSetsChanged();
		updateActionBars();

		// hide the launch menu if it is empty
		String path = IWorkbenchActionConstants.M_WINDOW + IWorkbenchActionConstants.SEP
				+ IWorkbenchActionConstants.M_LAUNCH;
		IMenuManager manager = getMenuBarManager().findMenuUsingPath(path);
		IContributionItem item = getMenuBarManager().findUsingPath(path);

		if (manager == null || item == null) {
			return;
		}
		item.setVisible(manager.getItems().length >= 2);
		// there is a separator for the additions group thus >= 2
	}

	private ListenerList<IActionSetsListener> actionSetListeners = null;

	private ListenerList<IBackgroundSaveListener> backgroundSaveListeners = new ListenerList<>(ListenerList.IDENTITY);

	private SelectionService selectionService;

	private ActionPresentation actionPresentation;

	private final void fireActionSetsChanged() {
		if (actionSetListeners != null) {
			for (Object listener : actionSetListeners.getListeners()) {
				final IActionSetsListener actionSetsListener = (IActionSetsListener) listener;
				final WorkbenchPage currentPage = (WorkbenchPage) getActivePage();
				final IActionSetDescriptor[] newActionSets;
				if (currentPage == null) {
					newActionSets = null;
				} else {
					newActionSets = currentPage.getActionSets();
				}
				final ActionSetsEvent event = new ActionSetsEvent(newActionSets);
				actionSetsListener.actionSetsChanged(event);
			}
		}
	}

	final void addActionSetsListener(final IActionSetsListener listener) {
		if (actionSetListeners == null) {
			actionSetListeners = new ListenerList<>();
		}

		actionSetListeners.add(listener);
	}

	final void removeActionSetsListener(final IActionSetsListener listener) {
		if (actionSetListeners != null) {
			actionSetListeners.remove(listener);
			if (actionSetListeners.isEmpty()) {
				actionSetListeners = null;
			}
		}
	}

	/**
	 * Returns whether the heap status indicator should be shown.
	 *
	 * @return <code>true</code> to show the heap status indicator,
	 *         <code>false</code> otherwise
	 */
	private boolean getShowHeapStatus() {
		return // Show if the preference is set or debug option is on
		PrefUtil.getAPIPreferenceStore().getBoolean(IWorkbenchPreferenceConstants.SHOW_MEMORY_MONITOR) || Boolean
				.valueOf(Platform.getDebugOption(PlatformUI.PLUGIN_ID + "/perf/showHeapStatus")).booleanValue(); //$NON-NLS-1$
	}

	public void showHeapStatus(boolean show) {
		MUIElement hsElement = modelService.find("org.eclipse.ui.HeapStatus", model); //$NON-NLS-1$
		if (hsElement != null && hsElement.isToBeRendered() != show) {
			hsElement.setToBeRendered(show);
			Object widget = hsElement.getParent().getWidget();
			if (widget instanceof Control) {
				((Control) widget).requestLayout();
			}
		}
	}

	/**
	 * Returns the unique object that applications use to configure this window.
	 * <p>
	 * IMPORTANT This method is declared package-private to prevent regular plug-ins
	 * from downcasting IWorkbenchWindow to WorkbenchWindow and getting hold of the
	 * workbench window configurer that would allow them to tamper with the
	 * workbench window. The workbench window configurer is available only to the
	 * application.
	 * </p>
	 */
	/* package - DO NOT CHANGE */
	WorkbenchWindowConfigurer getWindowConfigurer() {
		if (windowConfigurer == null) {
			// lazy initialize
			windowConfigurer = new WorkbenchWindowConfigurer(this);
		}
		return windowConfigurer;
	}

	/**
	 * Returns the workbench advisor. Assumes the workbench has been created
	 * already.
	 * <p>
	 * IMPORTANT This method is declared private to prevent regular plug-ins from
	 * downcasting IWorkbenchWindow to WorkbenchWindow and getting hold of the
	 * workbench advisor that would allow them to tamper with the workbench. The
	 * workbench advisor is internal to the application.
	 * </p>
	 */
	private/* private - DO NOT CHANGE */
	WorkbenchAdvisor getAdvisor() {
		return getWorkbenchImpl().getAdvisor();
	}

	/**
	 * Returns the window advisor, creating a new one for this window if needed.
	 * <p>
	 * IMPORTANT This method is declared package private to prevent regular plug-ins
	 * from downcasting IWorkbenchWindow to WorkbenchWindow and getting hold of the
	 * window advisor that would allow them to tamper with the window. The window
	 * advisor is internal to the application.
	 * </p>
	 */
	/* package private - DO NOT CHANGE */
	WorkbenchWindowAdvisor getWindowAdvisor() {
		if (windowAdvisor == null) {
			windowAdvisor = getAdvisor().createWorkbenchWindowAdvisor(getWindowConfigurer());
			Assert.isNotNull(windowAdvisor);
		}
		return windowAdvisor;
	}

	/**
	 * Returns the action bar advisor, creating a new one for this window if needed.
	 * <p>
	 * IMPORTANT This method is declared private to prevent regular plug-ins from
	 * downcasting IWorkbenchWindow to WorkbenchWindow and getting hold of the
	 * action bar advisor that would allow them to tamper with the window's action
	 * bars. The action bar advisor is internal to the application.
	 * </p>
	 */
	private/* private - DO NOT CHANGE */
	ActionBarAdvisor getActionBarAdvisor() {
		if (actionBarAdvisor == null) {
			actionBarAdvisor = getWindowAdvisor()
					.createActionBarAdvisor(getWindowConfigurer().getActionBarConfigurer());
			Assert.isNotNull(actionBarAdvisor);
		}
		return actionBarAdvisor;
	}

	/*
	 * Returns the IWorkbench implementation.
	 */
	private Workbench getWorkbenchImpl() {
		return Workbench.getInstance();
	}

	/**
	 * Fills the window's real action bars.
	 *
	 * @param flags indicate which bars to fill
	 */
	public void fillActionBars(int flags) {
		Workbench workbench = getWorkbenchImpl();
		workbench.largeUpdateStart();
		try {
			getActionBarAdvisor().fillActionBars(flags);
		} finally {
			workbench.largeUpdateEnd();
		}
	}

	/**
	 * Fills the window's proxy action bars.
	 *
	 * @param proxyBars the proxy configurer
	 * @param flags     indicate which bars to fill
	 */
	public void fillActionBars(IActionBarConfigurer2 proxyBars, int flags) {
		Assert.isNotNull(proxyBars);
		WorkbenchWindowConfigurer.WindowActionBarConfigurer wab = (WorkbenchWindowConfigurer.WindowActionBarConfigurer) getWindowConfigurer()
				.getActionBarConfigurer();
		wab.setProxy(proxyBars);
		try {
			getActionBarAdvisor().fillActionBars(flags | ActionBarAdvisor.FILL_PROXY);
		} finally {
			wab.setProxy(null);
		}
	}

	/**
	 * Cause the coolbar to be shown or hidden; note that the coolbar may still be
	 * visible depending on the visibility state of other elements. This method is a
	 * lower-level method that affects the visibility but does not update any
	 * associated preference values.
	 *
	 * @param visible whether the cool bar should be shown. This is only applicable
	 *                if the window configurer also wishes either the cool bar to be
	 *                visible.
	 * @since 3.0
	 */
	public void setCoolBarVisible(boolean visible) {
		boolean oldValue = coolBarVisible;
		coolBarVisible = visible;
		if (oldValue != coolBarVisible) {
			getModel().getPersistedState().put(IPreferenceConstants.COOLBAR_VISIBLE, Boolean.toString(visible));
			updateLayoutDataForContents();
			firePropertyChanged(PROP_COOLBAR_VISIBLE, oldValue ? Boolean.TRUE : Boolean.FALSE,
					coolBarVisible ? Boolean.TRUE : Boolean.FALSE);
		}
	}

	/**
	 * @return whether the cool bar should be shown. This is only applicable if the
	 *         window configurer also wishes either the cool bar to be visible.
	 * @since 3.0
	 */
	public boolean getCoolBarVisible() {
		return getWindowConfigurer().getShowCoolBar() && coolBarVisible;
	}

	public ActionPresentation getActionPresentation() {
		if (actionPresentation == null) {
			actionPresentation = new ActionPresentation(this);
		}
		return actionPresentation;
	}

	/**
	 * Cause the perspective bar to be shown or hidden; note that the perspective
	 * bar may still be visible depending on the visibility state of other elements.
	 * This method is a lower-level method that affects the visibility but does not
	 * update any associated preference values.
	 *
	 * @param visible whether the perspective bar should be shown. This is only
	 *                applicable if the window configurer also wishes either the
	 *                perspective bar to be visible.
	 * @since 3.0
	 */
	public void setPerspectiveBarVisible(boolean visible) {
		boolean oldValue = perspectiveBarVisible;
		perspectiveBarVisible = visible;
		if (oldValue != perspectiveBarVisible) {
			getModel().getPersistedState().put(IPreferenceConstants.PERSPECTIVEBAR_VISIBLE, Boolean.toString(visible));
			updateLayoutDataForContents();
			firePropertyChanged(PROP_PERSPECTIVEBAR_VISIBLE, oldValue ? Boolean.TRUE : Boolean.FALSE,
					perspectiveBarVisible ? Boolean.TRUE : Boolean.FALSE);
		}
	}

	/**
	 * @return whether the perspective bar should be shown. This is only applicable
	 *         if the window configurer also wishes either the perspective bar to be
	 *         visible.
	 * @since 3.0
	 */
	public boolean getPerspectiveBarVisible() {
		return getWindowConfigurer().getShowPerspectiveBar() && perspectiveBarVisible;
	}

	/**
	 * @param visible whether the perspective bar should be shown. This is only
	 *                applicable if the window configurer also wishes either the
	 *                perspective bar to be visible.
	 * @since 3.0
	 */
	public void setStatusLineVisible(boolean visible) {
		boolean oldValue = statusLineVisible;
		statusLineVisible = visible;
		if (oldValue != statusLineVisible) {
			getModel().getPersistedState().put(IPreferenceConstants.PERSPECTIVEBAR_VISIBLE, Boolean.toString(visible));
			updateLayoutDataForContents();
			firePropertyChanged(PROP_STATUS_LINE_VISIBLE, oldValue ? Boolean.TRUE : Boolean.FALSE,
					statusLineVisible ? Boolean.TRUE : Boolean.FALSE);
		}
	}

	/**
	 * @return whether the perspective bar should be shown. This is only applicable
	 *         if the window configurer also wishes either the perspective bar to be
	 *         visible.
	 * @since 3.0
	 */
	public boolean getStatusLineVisible() {
		return statusLineVisible;
	}

	protected boolean showTopSeperator() {
		return false;
	}

	/**
	 * @return Returns the progressRegion.
	 */
	public ProgressRegion getProgressRegion() {
		return progressRegion;
	}

	@Override
	public IExtensionTracker getExtensionTracker() {
		if (model == null || model.getContext() == null) {
			return null;
		}
		return model.getContext().get(IExtensionTracker.class);
	}

	/**
	 * Returns the default page input for workbench pages opened in this window.
	 *
	 * @return the default page input or <code>null</code> if none
	 * @since 3.1
	 */
	IAdaptable getDefaultPageInput() {
		return getWorkbenchImpl().getDefaultPageInput();
	}

	/**
	 * Initializes all of the default command-based services for the workbench
	 * window.
	 */
	private final void initializeDefaultServices() {
		IEclipseContext windowContext = model.getContext();
		serviceLocator.registerService(IWorkbenchLocationService.class,
				new WorkbenchLocationService(IServiceScopes.WINDOW_SCOPE, getWorkbench(), this, null, null, null, 1));
		// added back for legacy reasons
		serviceLocator.registerService(IWorkbenchWindow.class, this);

		final ActionCommandMappingService mappingService = new ActionCommandMappingService();
		serviceLocator.registerService(IActionCommandMappingService.class, mappingService);

		selectionService = ContextInjectionFactory.make(SelectionService.class, model.getContext());
		serviceLocator.registerService(ISelectionService.class, selectionService);

		LegacyHandlerService hs = new LegacyHandlerService(windowContext);
		windowContext.set(IHandlerService.class.getName(), hs);

		final LegacyActionPersistence actionPersistence = new LegacyActionPersistence(this);
		serviceLocator.registerService(LegacyActionPersistence.class, actionPersistence);
		actionPersistence.read();

		ICommandService cmdService = workbench.getService(ICommandService.class);
		SlaveCommandService slaveCmdService = new SlaveCommandService(cmdService, IServiceScopes.WINDOW_SCOPE, this,
				model.getContext());
		serviceLocator.registerService(ICommandService.class, slaveCmdService);
		serviceLocator.registerService(IUpdateService.class, slaveCmdService);

		IContextService cxs = ContextInjectionFactory.make(ContextService.class, model.getContext());
		serviceLocator.registerService(IContextService.class, cxs);

		IMenuService parent = getWorkbench().getService(IMenuService.class);
		IMenuService msvs = new SlaveMenuService(parent, model);
		serviceLocator.registerService(IMenuService.class, msvs);
	}

	@Override
	public final <T> T getService(final Class<T> key) {
		return serviceLocator.getService(key);
	}

	@Override
	public final boolean hasService(final Class<?> key) {
		return serviceLocator.hasService(key);
	}

	/**
	 * Toggle the visibility of the coolbar/perspective bar. This method respects
	 * the window configurer and will only toggle visibility if the item in question
	 * was originally declared visible by the window advisor.
	 *
	 * @since 3.3
	 */
	public void toggleToolbarVisibility() {
		boolean coolbarVisible = getCoolBarVisible();
		boolean perspectivebarVisible = getPerspectiveBarVisible();

		// only toggle the visibility of the components that
		// were on initially
		if (getWindowConfigurer().getShowCoolBar()) {
			setCoolBarVisible(!coolbarVisible);
		}
		if (getWindowConfigurer().getShowPerspectiveBar()) {
			setPerspectiveBarVisible(!perspectivebarVisible);
		}
		ICommandService commandService = getService(ICommandService.class);
		Map<String, WorkbenchWindow> filter = new HashMap<>();
		filter.put(IServiceScopes.WINDOW_SCOPE, this);
		commandService.refreshElements(COMMAND_ID_TOGGLE_COOLBAR, filter);
	}

	/**
	 * Return true if the toolbar is visible. Note that it may not be possible to
	 * make the toolbar visible (i.e., the window configurer).
	 *
	 * @return true if the toolbar is visible
	 * @since 4.2
	 */
	public boolean isToolbarVisible() {
		return (getCoolBarVisible() && getWindowConfigurer().getShowCoolBar())
				|| (getPerspectiveBarVisible() && getWindowConfigurer().getShowPerspectiveBar());
	}

	private void updateLayoutDataForContents() {
		MTrimBar topTrim = getTopTrim();
		if (topTrim != null) {
			topTrim.setVisible(isToolbarVisible());
			Shell shell = getShell();
			if (shell != null && !shell.isDisposed()) {
				shell.layout();
			}
		}
	}

	/* package */void addBackgroundSaveListener(IBackgroundSaveListener listener) {
		backgroundSaveListeners.add(listener);
	}

	/* package */void fireBackgroundSaveStarted() {
		for (Object listener : backgroundSaveListeners.getListeners()) {
			IBackgroundSaveListener backgroundSaveListener = (IBackgroundSaveListener) listener;
			backgroundSaveListener.handleBackgroundSaveStarted();
		}
	}

	/* package */void removeBackgroundSaveListener(IBackgroundSaveListener listener) {
		backgroundSaveListeners.remove(listener);
	}

	public MWindow getModel() {
		return model;
	}

	StatusLineManager statusLineManager = null;

	public StatusLineManager getStatusLineManager() {
		if (statusLineManager == null) {
			statusLineManager = new StatusLineManager();
		}
		return statusLineManager;
	}

	private CoolBarManager2 oldCBM = new CoolBarManager2();
	private CoolBarToTrimManager coolbarToTrim;

	public ICoolBarManager getCoolBarManager2() {
		if (coolbarToTrim == null) {
			coolbarToTrim = new CoolBarToTrimManager(application, model, workbenchTrimElements, rendererFactory);
		}
		return coolbarToTrim;
	}

	public CoolBarManager getCoolBarManager() {
		WorkbenchPlugin.log(new Exception("Bad call to getCoolBarManager()")); //$NON-NLS-1$
		return oldCBM;
	}

	private IContributionManagerOverrides toolbarOverride;

	static class ToolbarOverrides implements IContributionManagerOverrides {

		private WorkbenchPage page;

		ToolbarOverrides(WorkbenchPage page) {
			this.page = page;
		}

		@Override
		public Integer getAccelerator(IContributionItem item) {
			return null;
		}

		@Override
		public String getAcceleratorText(IContributionItem item) {
			return null;
		}

		@Override
		public Boolean getEnabled(IContributionItem item) {
			return null;
		}

		@Override
		public String getText(IContributionItem item) {
			return null;
		}

		@Override
		public Boolean getVisible(IContributionItem item) {
			if (page == null)
				return null;

			MPerspective curPersp = page.getCurrentPerspective();
			if (curPersp == null)
				return null;

			// Find the command ID
			String id = CustomizePerspectiveDialog.getIDFromIContributionItem(item);
			if (id == null)
				return null;

			String hiddenToolItems = page.getHiddenItems();
			if (hiddenToolItems.contains(ModeledPageLayout.HIDDEN_TOOLBAR_PREFIX + id + ",")) { //$NON-NLS-1$
				return Boolean.FALSE;
			}
			return null;
		}
	}

	MenuManager menuManager = new MenuManager("MenuBar", IWorkbenchConstants.MAIN_MENU_ID); //$NON-NLS-1$

	public MenuManager getMenuManager() {
		return menuManager;
	}

	public IMenuManager getMenuBarManager() {
		return menuManager;
	}

	private IContributionManagerOverrides menuOverride;

	static class MenuOverrides implements IContributionManagerOverrides {

		private WorkbenchPage page;

		MenuOverrides(WorkbenchPage page) {
			this.page = page;
		}

		@Override
		public Integer getAccelerator(IContributionItem item) {
			return null;
		}

		@Override
		public String getAcceleratorText(IContributionItem item) {
			return null;
		}

		@Override
		public Boolean getEnabled(IContributionItem item) {
			return null;
		}

		@Override
		public String getText(IContributionItem item) {
			return null;
		}

		@Override
		public Boolean getVisible(IContributionItem item) {
			if (page == null)
				return null;

			MPerspective curPersp = page.getCurrentPerspective();
			if (curPersp == null)
				return null;

			// Find the command ID
			String id = CustomizePerspectiveDialog.getIDFromIContributionItem(item);
			if (id == null)
				return null;

			String hiddenToolItems = page.getHiddenItems();
			if (hiddenToolItems.contains(ModeledPageLayout.HIDDEN_MENU_PREFIX + id + ",")) { //$NON-NLS-1$
				return Boolean.FALSE;
			}
			return null;
		}
	}

	ToolBarManager2 toolBarManager = new ToolBarManager2();

	private Runnable menuUpdater;

	@Inject
	@Optional
	private ToolBarManagerRenderer toolBarManagerRenderer;

	public IToolBarManager2 getToolBarManager2() {
		return toolBarManager;
	}

	public IToolBarManager getToolBarManager() {
		return getToolBarManager2();
	}

	public CustomizePerspectiveDialog createCustomizePerspectiveDialog(Perspective persp, IEclipseContext context) {
		return new CustomizePerspectiveDialog(getWindowConfigurer(), persp, context);
	}

	private class WWinPartService extends PartService {

		@Override
		public void partActivated(IWorkbenchPart part) {
			super.partActivated(part);
			selectionService.notifyListeners(part);
		}

	}

	class WWinPartServiceSaveHandler extends PartServiceSaveHandler {

		public boolean saveParts(Collection<MPart> dirtyParts, boolean confirm, boolean closing, boolean addNonPartSources) {
			if (addNonPartSources || closing) {
				throw new UnsupportedOperationException();
			}
			return saveParts(dirtyParts, confirm);
		}
	}
}
