/*******************************************************************************
 * Copyright (c) 2008, 2020 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
 *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 429728, 430166, 441150, 442285, 472654, 495718
 *     Andrey Loskutov <loskutov@gmx.de> - Bug 337588, 388476, 461573
 *     Simon Scholz <simon.scholz@vogella.com> - Bug 442285, 487348
 *     Patrik Suzzi <psuzzi@gmail.com> - Bug 497618
 *     Christoph Läubrich - Bug 433465
 *******************************************************************************/
package org.eclipse.e4.ui.workbench.renderers.swt;

import static java.util.Collections.singletonList;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Consumer;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Named;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.core.di.extensions.Preference;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.ui.css.swt.dom.WidgetElement;
import org.eclipse.e4.ui.di.UIEventTopic;
import org.eclipse.e4.ui.di.UISynchronize;
import org.eclipse.e4.ui.internal.workbench.OpaqueElementUtil;
import org.eclipse.e4.ui.internal.workbench.renderers.swt.BasicPartList;
import org.eclipse.e4.ui.internal.workbench.renderers.swt.SWTRenderersMessages;
import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
import org.eclipse.e4.ui.internal.workbench.swt.CSSConstants;
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
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.MUILabel;
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.MPartSashContainer;
import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
import org.eclipse.e4.ui.model.application.ui.basic.MStackElement;
import org.eclipse.e4.ui.model.application.ui.basic.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.MPopupMenu;
import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
import org.eclipse.e4.ui.workbench.IPresentationEngine;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.e4.ui.workbench.UIEvents.EventTags;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.ISaveHandler;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.LegacyActionTools;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.Accessible;
import org.eclipse.swt.accessibility.AccessibleListener;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabFolder2Adapter;
import org.eclipse.swt.custom.CTabFolderEvent;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Monitor;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Widget;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;

/**
 * SWT default renderer for a MPartStack model elements
 *
 * Style bits for the underlying CTabFolder can be set via the
 * IPresentation.STYLE_OVERRIDE_KEY key
 *
 */
public class StackRenderer extends LazyStackRenderer {
	/**
	 *
	 */
	private static final String THE_PART_KEY = "thePart"; //$NON-NLS-1$

	/**
	 * Key to control the default default value of the "most recently used" order
	 * enablement
	 */
	public static final String MRU_KEY_DEFAULT = "enableMRUDefault"; //$NON-NLS-1$

	/**
	 * Key to control the actual boolean preference of the "most recently used"
	 * order enablement
	 */
	public static final String MRU_KEY = "enableMRU"; //$NON-NLS-1$

	/**
	 * Default default value for MRU behavior.
	 */
	public static final boolean MRU_DEFAULT = true;

	/*
	 * JFace key for default workbench tab font
	 */
	private static final String TAB_FONT_KEY = "org.eclipse.ui.workbench.TAB_TEXT_FONT"; //$NON-NLS-1$

	@Inject
	@Preference(nodePath = "org.eclipse.e4.ui.workbench.renderers.swt")
	private IEclipsePreferences preferences;

	@Inject
	@Named(WorkbenchRendererFactory.SHARED_ELEMENTS_STORE)
	Map<MUIElement, Set<MPlaceholder>> renderedMap;

	public static final String TAG_VIEW_MENU = "ViewMenu"; //$NON-NLS-1$
	private static final String SHELL_CLOSE_EDITORS_MENU = "shell_close_editors_menu"; //$NON-NLS-1$
	private static final String STACK_SELECTED_PART = "stack_selected_part"; //$NON-NLS-1$

	/**
	 * Add this tag to prevent the next tab's activation from granting focus toac
	 * the part. This is used to keep the focus on the CTabFolder when traversing
	 * the tabs using the keyboard.
	 */
	private static final String INHIBIT_FOCUS = "InhibitFocus"; //$NON-NLS-1$

	// Minimum characters in for stacks outside the shared area
	private static int MIN_VIEW_CHARS = 1;

	// Minimum characters in for stacks inside the shared area
	private static int MIN_EDITOR_CHARS = 15;

	private Image viewMenuImage;
	private String viewMenuURI = "platform:/plugin/org.eclipse.e4.ui.workbench.renderers.swt/icons/full/elcl16/view_menu.png"; //$NON-NLS-1$

	@Inject
	private IEventBroker eventBroker;

	@Inject
	private IPresentationEngine renderer;

	private boolean ignoreTabSelChanges;

	private TabStateHandler tabStateHandler;

	private boolean imageChanged;

	List<CTabItem> getItemsToSet(MPart part) {
		List<CTabItem> itemsToSet = new ArrayList<>();

		MUIElement partParent = part.getParent();
		if (partParent instanceof MPartStack) {
			addItemToSet(itemsToSet, part);
		} else if (partParent instanceof MPartSashContainer) {
			MElementContainer<MUIElement> parentParent = partParent.getParent();
			if (parentParent instanceof MPart) {
				MPart parentParentMPart = (MPart) parentParent;
				addItemToSet(itemsToSet, parentParentMPart);
			}
		} else if (part.getCurSharedRef() != null) {
			MWindow topWin = modelService.getTopLevelWindowFor(part);
			List<MPlaceholder> partRefs = modelService.findElements(topWin, part.getElementId(), MPlaceholder.class);
			for (MPlaceholder ref : partRefs) {
				CTabItem item = findItemForPart(ref, null);
				if (item != null) {
					itemsToSet.add(item);
				}
			}
		}

		return itemsToSet;
	}

	private void addItemToSet(List<CTabItem> itemsToSet, MPart parentParent) {
		CTabItem item = findItemForPart(parentParent);
		if (item != null) {
			itemsToSet.add(item);
		}
	}

	@SuppressWarnings("unchecked")
	@Inject
	@Optional
	void subscribeTopicTransientDataChanged(
			@UIEventTopic(UIEvents.ApplicationElement.TOPIC_TRANSIENTDATA) org.osgi.service.event.Event event) {
		Object changedElement = event.getProperty(UIEvents.EventTags.ELEMENT);

		if (!(changedElement instanceof MPart))
			return;

		String key;
		if (UIEvents.isREMOVE(event)) {
			key = ((Entry<String, Object>) event.getProperty(UIEvents.EventTags.OLD_VALUE)).getKey();
		} else {
			key = ((Entry<String, Object>) event.getProperty(UIEvents.EventTags.NEW_VALUE)).getKey();
		}

		if (!IPresentationEngine.OVERRIDE_ICON_IMAGE_KEY.equals(key)
				&& !IPresentationEngine.OVERRIDE_TITLE_TOOL_TIP_KEY.equals(key))
			return;

		MPart part = (MPart) changedElement;
		List<CTabItem> itemsToSet = getItemsToSet(part);
		for (CTabItem item : itemsToSet) {
			if (key.equals(IPresentationEngine.OVERRIDE_ICON_IMAGE_KEY)) {
				changePartTabImage(part, item);
			} else if (key.equals(IPresentationEngine.OVERRIDE_TITLE_TOOL_TIP_KEY)) {
				String newTip = getToolTip(part);
				item.setToolTipText(getToolTip(newTip));
			}
		}
	}

	/**
	 * Handles changes in tags
	 *
	 * @param event
	 */
	@Inject
	@Optional
	void subscribeTopicTagsChanged(@UIEventTopic(UIEvents.ApplicationElement.TOPIC_TAGS) Event event) {

		if (tabStateHandler == null) {
			tabStateHandler = new TabStateHandler();
		}
		tabStateHandler.handleEvent(event);

		Object changedObj = event.getProperty(EventTags.ELEMENT);

		if (!(changedObj instanceof MPart))
			return;

		final MPart part = (MPart) changedObj;
		CTabItem item = findItemForPart(part);
		if (item == null || item.isDisposed())
			return;

		if (UIEvents.isADD(event)) {
			if (UIEvents.contains(event, UIEvents.EventTags.NEW_VALUE, IPresentationEngine.ADORNMENT_PIN)) {
				item.setImage(getImage(part));
			}
		} else if (UIEvents.isREMOVE(event)) {
			if (UIEvents.contains(event, UIEvents.EventTags.OLD_VALUE, IPresentationEngine.ADORNMENT_PIN)) {
				item.setImage(getImage(part));
			}
		}
	}

	@Inject
	@Optional
	void subscribeTopicChildrenChanged(@UIEventTopic(UIEvents.ElementContainer.TOPIC_CHILDREN) Event event) {
		shouldTopRightAdjusted(event);
	}

	@Inject
	@Optional
	void subscribeTopicUILabelChanged(@UIEventTopic(UIEvents.UILabel.TOPIC_ALL) Event event) {
		Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
		if (!(element instanceof MPart))
			return;

		MPart part = (MPart) element;

		String attName = (String) event.getProperty(UIEvents.EventTags.ATTNAME);
		Object newValue = event.getProperty(UIEvents.EventTags.NEW_VALUE);

		// is this a direct child of the stack?
		if (part.getParent() != null && part.getParent().getRenderer() == StackRenderer.this) {
			CTabItem cti = findItemForPart(part);
			if (cti != null) {
				updateTab(cti, part, attName, newValue);
			}
			return;
		}

		// Do we have any stacks with place holders for the element
		// that's changed?
		MWindow win = modelService.getTopLevelWindowFor(part);
		List<MPlaceholder> refs = modelService.findElements(win, null, MPlaceholder.class, null);
		if (refs != null) {
			for (MPlaceholder ref : refs) {
				if (ref.getRef() != part)
					continue;

				MElementContainer<MUIElement> refParent = ref.getParent();
				// can be null, see bug 328296
				if (refParent != null && refParent.getRenderer() instanceof StackRenderer) {
					CTabItem cti = findItemForPart(ref, refParent);
					if (cti != null) {
						updateTab(cti, part, attName, newValue);
					}
				}
			}
		}
	}

	@Inject
	@Optional
	void subscribeTopicDirtyChanged(@UIEventTopic(UIEvents.Dirtyable.TOPIC_DIRTY) Event event) {
		Object objElement = event.getProperty(UIEvents.EventTags.ELEMENT);

		// Ensure that this event is for a MMenuItem
		if (!(objElement instanceof MPart)) {
			return;
		}

		// Extract the data bits
		MPart part = (MPart) objElement;

		updatePartTab(event, part);
	}

	@Inject
	@Optional
	void subscribeTopicClosablePartChanged(@UIEventTopic(UIEvents.Part.TOPIC_CLOSEABLE) Event event) {
		updateClosableTab(event);
	}

	@Inject
	@Optional
	void subscribeTopicClosablePlaceholderChanged(@UIEventTopic(UIEvents.Placeholder.TOPIC_CLOSEABLE) Event event) {
		updateClosableTab(event);
	}

	private void updateClosableTab(Event event) {
		Object element = event.getProperty(UIEvents.EventTags.ELEMENT);

		MPart part = null;
		if (element instanceof MPart) {
			part = (MPart) element;
		} else if (element instanceof MPlaceholder) {
			MUIElement ref = ((MPlaceholder) element).getRef();
			if (ref instanceof MPart) {
				part = (MPart) ref;
			}
		}

		if (part == null) {
			return;
		}

		updatePartTab(event, part);
	}

	private void updatePartTab(Event event, MPart part) {
		String attName = (String) event.getProperty(UIEvents.EventTags.ATTNAME);
		Object newValue = event.getProperty(UIEvents.EventTags.NEW_VALUE);

		// Is the part directly under the stack?
		MElementContainer<MUIElement> parent = part.getParent();
		if (parent != null && parent.getRenderer() == StackRenderer.this) {
			CTabItem cti = findItemForPart(part, parent);
			if (cti != null) {
				updateTab(cti, part, attName, newValue);
			}
			return;
		}

		// Do we have any stacks with place holders for the element
		// that's changed?
		Set<MPlaceholder> refs = renderedMap.get(part);
		if (refs != null) {
			for (MPlaceholder ref : refs) {
				MElementContainer<MUIElement> refParent = ref.getParent();
				if (refParent.getRenderer() instanceof StackRenderer) {
					CTabItem cti = findItemForPart(ref, refParent);
					if (cti != null) {
						updateTab(cti, part, attName, newValue);
					}
				}
			}
		}
	}

	@Inject
	@Optional
	void subscribeTopicVisibleChanged(@UIEventTopic(UIEvents.UIElement.TOPIC_VISIBLE) Event event) {
		shouldTopRightAdjusted(event);
	}

	@Inject
	@Optional
	void subscribeTopicToBeRenderedChanged(@UIEventTopic(UIEvents.UIElement.TOPIC_TOBERENDERED) Event event) {
		shouldTopRightAdjusted(event);
	}

	@Inject
	@Optional
	private UISynchronize synchronize;

	/**
	 * An event handler for listening to changes to the state of view menus and part
	 * toolbars. Depending on what state these items are in, the view menu and
	 * toolbar should or should not be rendered on the tab folder.
	 */
	private void shouldTopRightAdjusted(Event event) {
		Object objElement = event.getProperty(UIEvents.EventTags.ELEMENT);

		// Ensure that this event is for a MMenuItem or MToolBar
		if (!(objElement instanceof MMenuElement && !(objElement instanceof MPopupMenu))
				&& !(objElement instanceof MToolBar)) {
			return;
		}

		// Ensure that it's a View part's menu or toolbar
		MUIElement uiElement = (MUIElement) objElement;
		MUIElement parent = modelService.getContainer(uiElement);
		if (!(parent instanceof MPart)) {
			return;
		}

		// Get the partstack and the element in the partstack
		MStackElement element = (MPart) parent;
		if (element.getCurSharedRef() != null) {
			element = element.getCurSharedRef();
		}
		MUIElement parentElement = element.getParent();

		if (!(parentElement instanceof MPartStack)) {
			return;
		}

		Object widget = parentElement.getWidget();
		if (widget instanceof CTabFolder) {
			// The widget is created by the PartRenderingEngine, however the order of this
			// call and the call in the engine are unknown. Therefore, call it
			// asynchronously such that it is always last.
			synchronize.asyncExec(() -> adjustTopRight((CTabFolder) widget));
		}
	}

	@Inject
	@Optional
	void subscribeTopicActivateChanged(@UIEventTopic(UIEvents.UILifeCycle.ACTIVATE) Event event) {
		// Manages CSS styling based on active part changes
		MUIElement changed = (MUIElement) event.getProperty(UIEvents.EventTags.ELEMENT);
		if (!(changed instanceof MPart)) {
			return;
		}

		MPart newActivePart = (MPart) changed;
		MUIElement partParent = newActivePart.getParent();
		if (partParent == null && newActivePart.getCurSharedRef() != null) {
			partParent = newActivePart.getCurSharedRef().getParent();
		}

		// Skip sash containers
		while (partParent != null && partParent instanceof MPartSashContainer) {
			partParent = partParent.getParent();
		}

		// Ensure the stack of a split part gets updated when one
		// of its internal parts gets activated
		if (partParent instanceof MCompositePart) {
			partParent = partParent.getParent();
		}

		MPartStack pStack = (MPartStack) (partParent instanceof MPartStack ? partParent : null);

		List<MUIElement> activeElements = modelService.findElements(modelService.getTopLevelWindowFor(newActivePart),
				null, MUIElement.class, singletonList(CSSConstants.CSS_ACTIVE_CLASS));
		for (MUIElement element : activeElements) {
			if (element instanceof MPartStack && element != pStack) {
				styleElement(element, false);
			} else if (element instanceof MPart && element != newActivePart) {
				styleElement(element, false);
			}
		}

		if (pStack != null) {
			styleElement(pStack, true);
		}
		styleElement(newActivePart, true);
	}

	@Inject
	@Optional
	void subscribeTopicSelectedelementChanged(
			@UIEventTopic(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT) Event event) {
		if (tabStateHandler == null) {
			tabStateHandler = new TabStateHandler();
		}
		tabStateHandler.handleEvent(event);
	}

	@Override
	protected boolean requiresFocus(MPart element) {
		MUIElement inStack = element.getCurSharedRef() != null ? element.getCurSharedRef() : element;
		if (inStack.getParent() != null && inStack.getParent().getTransientData().containsKey(INHIBIT_FOCUS)) {
			inStack.getParent().getTransientData().remove(INHIBIT_FOCUS);
			return false;
		}

		return super.requiresFocus(element);
	}

	@PostConstruct
	public void init() {
		super.init(eventBroker);
	}

	protected void updateTab(CTabItem cti, MPart part, String attName, Object newValue) {
		switch (attName) {
		case UIEvents.UILabel.LABEL:
		case UIEvents.UILabel.LOCALIZED_LABEL:
			String newName = (String) newValue;
			cti.setText(getLabel(part, newName));
			break;
		case UIEvents.Dirtyable.DIRTY:
			cti.setText(getLabel(part, part.getLocalizedLabel()));
			break;
		case UIEvents.UILabel.ICONURI:
			changePartTabImage(part, cti);
			break;
		case UIEvents.UILabel.TOOLTIP:
		case UIEvents.UILabel.LOCALIZED_TOOLTIP:
			String newTTip = (String) newValue;
			cti.setToolTipText(getToolTip(newTTip));
			break;
		case UIEvents.Part.CLOSEABLE:
			Boolean closeableState = (Boolean) newValue;
			cti.setShowClose(closeableState.booleanValue());
			break;
		default:
			break;
		}
	}

	private void changePartTabImage(MPart part, CTabItem item) {
		this.imageChanged = true;
		item.setImage(getImage(part));
		this.imageChanged = false;
	}

	@PreDestroy
	public void contextDisposed() {
		super.contextDisposed(eventBroker);
	}

	private String getLabel(MUILabel itemPart, String newName) {
		if (newName == null) {
			newName = ""; //$NON-NLS-1$
		} else {
			newName = LegacyActionTools.escapeMnemonics(newName);
		}

		if (itemPart instanceof MDirtyable && ((MDirtyable) itemPart).isDirty()) {
			newName = '*' + newName;
		}
		return newName;
	}

	private String getToolTip(String newToolTip) {
		return newToolTip == null || newToolTip.length() == 0 ? null : LegacyActionTools.escapeMnemonics(newToolTip);
	}

	@Override
	public Object createWidget(MUIElement element, Object parent) {
		if (!(element instanceof MPartStack) || !(parent instanceof Composite))
			return null;

		MPartStack pStack = (MPartStack) element;

		Composite parentComposite = (Composite) parent;

		// Ensure that all rendered PartStacks have an Id
		if (element.getElementId() == null || element.getElementId().length() == 0) {
			String generatedId = "PartStack@" + Integer.toHexString(element.hashCode()); //$NON-NLS-1$
			element.setElementId(generatedId);
		}

		int styleOverride = getStyleOverride(pStack);
		int style = styleOverride == -1 ? SWT.BORDER : styleOverride;
		final CTabFolder tabFolder = new CTabFolder(parentComposite, style);
		tabFolder.setMRUVisible(getMRUValue(tabFolder));

		// Adjust the minimum chars based on the location
		int location = modelService.getElementLocation(element);
		if ((location & EModelService.IN_SHARED_AREA) != 0) {
			tabFolder.setMinimumCharacters(MIN_EDITOR_CHARS);
			tabFolder.setUnselectedCloseVisible(true);
		} else {
			tabFolder.setMinimumCharacters(MIN_VIEW_CHARS);
			tabFolder.setUnselectedCloseVisible(false);
		}

		bindWidget(element, tabFolder); // ?? Do we need this ?

		// Add a composite to manage the view's TB and Menu
		addTopRight(tabFolder);

		return tabFolder;
	}

	private boolean getMRUValue(Control control) {
		return getMRUValueFromPreferences();
	}

	private boolean getMRUValueFromPreferences() {
		boolean initialMRUValue = preferences.getBoolean(MRU_KEY_DEFAULT, MRU_DEFAULT);
		return preferences.getBoolean(MRU_KEY, initialMRUValue);
	}

	private void updateMRUValue(CTabFolder tabFolder) {
		boolean actualMRUValue = getMRUValue(tabFolder);
		tabFolder.setMRUVisible(actualMRUValue);
	}

	/**
	 * @param tabFolder
	 */
	private void addTopRight(CTabFolder tabFolder) {
		Composite trComp = new Composite(tabFolder, SWT.NONE);
		RowLayout rl = new RowLayout();
		trComp.setLayout(rl);
		rl.spacing = 0;
		rl.marginBottom = rl.marginTop = rl.marginRight = rl.marginLeft = 0;
		tabFolder.setTopRight(trComp, SWT.RIGHT | SWT.WRAP);

		// Initially it's not visible
		trComp.setVisible(false);

		// Create a toolbar for the view's drop-down menu
		ToolBar menuTB = new ToolBar(trComp, SWT.FLAT | SWT.RIGHT);
		menuTB.setData(TAG_VIEW_MENU);
		tabFolder.setData(TAG_VIEW_MENU, menuTB);
		RowData rd = new RowData();
		menuTB.setLayoutData(rd);
		ToolItem ti = new ToolItem(menuTB, SWT.PUSH);
		ti.setImage(getViewMenuImage());
		ti.setHotImage(null);
		ti.setToolTipText(SWTRenderersMessages.viewMenu);

		// Initially it's not visible
		rd.exclude = true;
		menuTB.setVisible(false);

		ti.addSelectionListener(new SelectionListener() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				showMenu((ToolItem) e.widget);
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				showMenu((ToolItem) e.widget);
			}
		});
		menuTB.getAccessible().addAccessibleListener(AccessibleListener.getNameAdapter(e -> {
			if (e.childID != ACC.CHILDID_SELF) {
				Accessible accessible = (Accessible) e.getSource();
				ToolBar toolBar = (ToolBar) accessible.getControl();
				if (0 <= e.childID && e.childID < toolBar.getItemCount()) {
					ToolItem item = toolBar.getItem(e.childID);
					if (item != null) {
						e.result = item.getToolTipText();
					}
				}
			}
		}));

		// Set an initial bounds
		trComp.pack();
	}


	public void adjustTopRight(final CTabFolder tabFolder) {
		if (tabFolder.isDisposed()) {
			return;
		}

		// Gather the parameters
		MPartStack stack = (MPartStack) tabFolder.getData(OWNING_ME);
		MUIElement element = stack.getSelectedElement();
		MPart part = null;
		if (element != null) {
			part = (MPart) ((element instanceof MPart) ? element : ((MPlaceholder) element).getRef());
		}

		Composite trComp = (Composite) tabFolder.getTopRight();

		boolean needsTB = part != null && part.getToolbar() != null && part.getToolbar().isToBeRendered();

		// View menu (if any)
		MMenu viewMenu = getViewMenu(part);
		boolean needsMenu = viewMenu != null && hasVisibleMenuItems(viewMenu, part);

		// Check the current state of the TB's
		ToolBar menuTB = (ToolBar) tabFolder.getData(TAG_VIEW_MENU);

		// We need to modify the 'exclude' bit based on if the menuTB is
		// visible or not
		RowData rd = (RowData) menuTB.getLayoutData();
		if (needsMenu) {
			menuTB.getItem(0).setData(THE_PART_KEY, part);
			rd.exclude = false;
			menuTB.setVisible(true);
		} else {
			menuTB.getItem(0).setData(THE_PART_KEY, null);
			rd.exclude = true;
			menuTB.setVisible(false);
		}

		menuTB.moveBelow(null);

		if (needsMenu || needsTB) {
			tabFolder.getTopRight().setVisible(true);
		} else {
			tabFolder.getTopRight().setVisible(false);
		}

		// Pack the result
		try {
			trComp.setRedraw(false);
			trComp.pack();
			trComp.requestLayout();
		} finally {
			trComp.setRedraw(true);
		}

		updateMRUValue(tabFolder);
	}

	@Override
	protected void createTab(MElementContainer<MUIElement> stack, MUIElement element) {

		// an invisible element won't have the correct widget hierarchy
		if (!element.isVisible()) {
			return;
		}

		MPart part = null;
		if (element instanceof MPart)
			part = (MPart) element;
		else if (element instanceof MPlaceholder) {
			part = (MPart) ((MPlaceholder) element).getRef();
			if (part != null) {
				part.setCurSharedRef((MPlaceholder) element);
			}
		}

		CTabFolder tabFolder = (CTabFolder) stack.getWidget();

		CTabItem tabItem = findItemForPart(element, stack);
		if (tabItem != null) {
			if (element.getWidget() != null && tabItem.getControl() != element.getWidget())
				tabItem.setControl((Control) element.getWidget());
			return;
		}
		updateMRUValue(tabFolder);
		int createFlags = SWT.NONE;
		if (part != null && isClosable(part)) {
			createFlags |= SWT.CLOSE;
		}

		// Create the tab; we may have more visible tabs than currently shown
		// (e.g., a result of calling partStack.getChildren().addAll(partList))
		int index = Math.min(calcIndexFor(stack, element), tabFolder.getItemCount());
		tabItem = new CTabItem(tabFolder, createFlags, index);

		tabItem.setData(OWNING_ME, element);
		tabItem.setText(getLabel(part, part.getLocalizedLabel()));
		tabItem.setImage(getImage(part));

		String toolTip = getToolTip(part);
		if (toolTip == null)
			toolTip = part.getLocalizedTooltip();
		tabItem.setToolTipText(getToolTip(toolTip));
		if (element.getWidget() != null) {
			// The part might have a widget but may not yet have been placed
			// under this stack, check this
			Control control = (Control) element.getWidget();
			if (control.getParent() == tabFolder)
				tabItem.setControl((Control) element.getWidget());
		}
	}

	private int calcIndexFor(MElementContainer<MUIElement> stack, final MUIElement part) {
		int index = 0;

		// Find the -visible- part before this element
		for (MUIElement mPart : stack.getChildren()) {
			if (mPart == part)
				return index;
			if (mPart.isToBeRendered() && mPart.isVisible())
				index++;
		}
		return index;
	}

	@Override
	public void childRendered(final MElementContainer<MUIElement> parentElement, MUIElement element) {
		super.childRendered(parentElement, element);

		if (!(((MUIElement) parentElement) instanceof MPartStack) || !(element instanceof MStackElement))
			return;

		createTab(parentElement, element);
	}

	private CTabItem findItemForPart(MUIElement element, MElementContainer<MUIElement> stack) {
		if (stack == null)
			stack = element.getParent();
		if (!(stack.getWidget() instanceof CTabFolder))
			return null;
		CTabFolder tabFolder = (CTabFolder) stack.getWidget();
		if (tabFolder == null || tabFolder.isDisposed())
			return null;

		CTabItem[] items = tabFolder.getItems();
		for (CTabItem item : items) {
			if (item.getData(OWNING_ME) == element)
				return item;
		}
		return null;
	}

	public CTabItem findItemForPart(MPart part) {
		// Invisible parts don't have items
		if (!part.isToBeRendered())
			return null;

		// is this a direct child of the stack?
		if (part.getParent() != null && part.getParent().getRenderer() == StackRenderer.this) {
			CTabItem cti = findItemForPart(part, part.getParent());
			if (cti != null) {
				return cti;
			}
		}

		// Do we have any stacks with place holders for the element
		// that's changed?
		MWindow win = modelService.getTopLevelWindowFor(part);

		if (win == null)
			return null;

		List<MPlaceholder> refs = modelService.findElements(win, null, MPlaceholder.class);
		if (refs != null) {
			for (MPlaceholder ref : refs) {
				if (ref.getRef() != part)
					continue;

				MElementContainer<MUIElement> refParent = ref.getParent();
				// can be null, see bug 328296
				if (refParent != null && refParent.getRenderer() instanceof StackRenderer) {
					CTabItem cti = findItemForPart(ref, refParent);
					if (cti != null) {
						return cti;
					}
				}
			}
		}
		return null;
	}

	@Override
	public void hideChild(MElementContainer<MUIElement> parentElement, MUIElement child) {
		super.hideChild(parentElement, child);

		CTabFolder tabFolder = (CTabFolder) parentElement.getWidget();
		if (tabFolder == null)
			return;

		// Check if we have to reset the currently active child for the stack
		CTabItem tabItem = findItemForPart(child, parentElement);
		if (tabItem == tabFolder.getSelection()) {
			// If we're the only part we need to clear the top right...
			if (tabFolder.getItemCount() == 1) {
				adjustTopRight(tabFolder);
			}
		}

		// find the 'stale' tab for this element and dispose it
		if (tabItem != null && !tabItem.isDisposed()) {
			tabItem.setControl(null);
			tabItem.dispose();
		}
	}

	@Override
	public void hookControllerLogic(final MUIElement me) {
		super.hookControllerLogic(me);

		if (!(me instanceof MElementContainer<?>))
			return;

		@SuppressWarnings("unchecked")
		final MElementContainer<MUIElement> stack = (MElementContainer<MUIElement>) me;

		// Match the selected TabItem to its Part
		final CTabFolder tabFolder = (CTabFolder) me.getWidget();

		// Handle traverse events for accessibility
		tabFolder.addTraverseListener(e -> {
			if (e.detail == SWT.TRAVERSE_ARROW_NEXT || e.detail == SWT.TRAVERSE_ARROW_PREVIOUS) {
				me.getTransientData().put(INHIBIT_FOCUS, true);
			} else if (e.detail == SWT.TRAVERSE_RETURN) {
				me.getTransientData().remove(INHIBIT_FOCUS);
				CTabItem cti = tabFolder.getSelection();
				if (cti != null) {
					MUIElement stackElement = (MUIElement) cti.getData(OWNING_ME);
					if (stackElement instanceof MPlaceholder)
						stackElement = ((MPlaceholder) stackElement).getRef();
					if ((stackElement instanceof MPart) && (tabFolder.isFocusControl())) {
						MPart thePart = (MPart) stackElement;
						renderer.focusGui(thePart);
					}
				}
			}
		});

		// Detect activation...picks up cases where the user clicks on the
		// (already active) tab
		tabFolder.addListener(SWT.Activate, event -> {
			if (event.detail == SWT.MouseDown) {
				CTabFolder tabFolder1 = (CTabFolder) event.widget;
				if (tabFolder1.getSelection() == null)
					return;

				// get the item under the cursor
				Point cp = event.display.getCursorLocation();
				cp = event.display.map(null, tabFolder1, cp);
				CTabItem overItem = tabFolder1.getItem(cp);

				// If the item we're over is *not* the current one do
				// nothing (it'll get activated when the tab changes)
				if (overItem == null || overItem == tabFolder1.getSelection()) {
					MUIElement uiElement = (MUIElement) tabFolder1.getSelection().getData(OWNING_ME);
					if (uiElement instanceof MPlaceholder)
						uiElement = ((MPlaceholder) uiElement).getRef();
					if (uiElement instanceof MPart)
						activate((MPart) uiElement);
				}
			}
		});

		tabFolder.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
			// prevent recursions
			if (ignoreTabSelChanges)
				return;

			MUIElement ele = (MUIElement) e.item.getData(OWNING_ME);
			ele.getParent().setSelectedElement(ele);
			if (ele instanceof MPlaceholder)
				ele = ((MPlaceholder) ele).getRef();
			if (ele instanceof MPart)
				activate((MPart) ele);
		}));

		MouseListener mouseListener = new MouseAdapter() {

			@Override
			public void mouseDoubleClick(MouseEvent e) {
				CTabItem item = tabFolder.getSelection();
				if (item != null) {
					MUIElement ele = (MUIElement) item.getData(OWNING_ME);
					if (ele.getParent().getSelectedElement() == ele) {
						Control ctrl = (Control) ele.getWidget();
						if (ctrl != null) {
							ctrl.setFocus();
						}
					}
				}
			}

			@Override
			public void mouseUp(MouseEvent e) {
				if (tabFolder.isDisposed()) {
					// 517654: MouseUp may be sent after stack has been disposed
					return;
				}
				CTabItem item = tabFolder.getItem(new Point(e.x, e.y));

				// If the user middle clicks on a tab, close it
				if (item != null && e.button == 2) {
					closePart(item);
				}

				// If the user clicks on the tab or empty stack space, call
				// setFocus() to transfer it from the tabfolder to the client widget
				if (e.button == 1) {
					if (item == null) {
						Rectangle clientArea = tabFolder.getClientArea();
						if (!clientArea.contains(e.x, e.y)) {
							// User clicked in empty space
							item = tabFolder.getSelection();
						}
					}

					// but only transfer focus if we have it.
					// If we don't own it, the widget has already the focus
					// so don't set it second time
					if (item != null && tabFolder.isFocusControl()) {
						MUIElement ele = (MUIElement) item.getData(OWNING_ME);
						if (ele.getParent().getSelectedElement() == ele) {
							Control ctrl = (Control) ele.getWidget();
							if (ctrl != null) {
								ctrl.setFocus();
							}
						}
					}
				}
			}
		};
		tabFolder.addMouseListener(mouseListener);

		CTabFolder2Adapter closeListener = new CTabFolder2Adapter() {
			@Override
			public void close(CTabFolderEvent event) {
				event.doit = closePart(event.item);
			}

			@Override
			public void showList(CTabFolderEvent event) {
				event.doit = false;
				showAvailableItems(stack, tabFolder);
			}
		};
		tabFolder.addCTabFolder2Listener(closeListener);

		tabFolder.addMenuDetectListener(e -> {
			Point absolutePoint = new Point(e.x, e.y);
			Point relativePoint = tabFolder.getDisplay().map(null, tabFolder, absolutePoint);
			CTabItem eventTabItem = tabFolder.getItem(relativePoint);

			// If click happened in empty area, still show the menu
			if (eventTabItem == null) {
				Rectangle clientArea = tabFolder.getClientArea();
				if (!clientArea.contains(relativePoint)) {
					eventTabItem = tabFolder.getSelection();
				}
			}

			if (eventTabItem != null) {
				MUIElement uiElement = (MUIElement) eventTabItem.getData(AbstractPartRenderer.OWNING_ME);
				MPart tabPart = (MPart) ((uiElement instanceof MPart) ? uiElement
						: ((MPlaceholder) uiElement).getRef());
				openMenuFor(tabPart, tabFolder, absolutePoint);
			}
		});

		tabFolder.addControlListener(ControlListener.controlResizedAdapter(e -> updateMRUValue(tabFolder)));
	}

	/**
	 * Shows a popup dialog with the list of editors availavle in a given
	 * {@link CTabFolder}. By default the popup origin will be located close to the
	 * chevron location.
	 *
	 * @param stack
	 * @param tabFolder
	 */
	public void showAvailableItems(MElementContainer<?> stack, CTabFolder tabFolder) {
		showAvailableItems(stack, tabFolder, false);
	}

	/**
	 * Shows a popup dialog with the list of editors available in the given
	 * CTabFolder. If {@code forceCenter} enabled, the dialog is centered
	 * horizontally; otherwise, the dialog origin is placed at chevron location. he
	 * dialog is placed at
	 *
	 * @param stack
	 * @param tabFolder
	 * @param forceCenter center the dialog if true
	 */
	public void showAvailableItems(MElementContainer<?> stack, CTabFolder tabFolder, boolean forceCenter) {
		IEclipseContext ctxt = getContext(stack);
		final BasicPartList editorList = new BasicPartList(tabFolder.getShell(), SWT.ON_TOP,
				SWT.V_SCROLL | SWT.H_SCROLL, ctxt.get(EPartService.class), stack, this, getMRUValueFromPreferences());
		editorList.setInput();

		Point size = editorList.computeSizeHint();
		editorList.setSize(size.x, size.y);

		Point location = null;
		if (forceCenter) {
			// placed to the center
			Rectangle ca = tabFolder.getClientArea();
			location = tabFolder.toDisplay(ca.x, ca.y);
			location.x = Math.max(0, (location.x + ((ca.width - size.x) / 2)));
			location.y = Math.max(0, (location.y + ((ca.height - size.y) / 3)));
		} else {
			// placed at chevron location
			location = tabFolder.toDisplay(getChevronLocation(tabFolder));
			Monitor mon = tabFolder.getMonitor();
			Rectangle bounds = mon.getClientArea();
			if (location.x + size.x > bounds.x + bounds.width) {
				location.x = bounds.x + bounds.width - size.x;
			}
			if (location.y + size.y > bounds.y + bounds.height) {
				location.y = bounds.y + bounds.height - size.y;
			}
		}
		editorList.setLocation(location);

		editorList.setVisible(true);
		editorList.setFocus();
		editorList.getShell().addListener(SWT.Deactivate, event -> {
			editorList.getShell().getDisplay().asyncExec(() -> {
				if (!editorList.hasFocus()) {
					editorList.dispose();
				}
			});
		});
	}

	private Point getChevronLocation(CTabFolder tabFolder) {
		// get the last visible item
		int numItems = tabFolder.getItemCount();
		CTabItem item = null;
		for (int i = 0; i < numItems; i++) {
			CTabItem tempItem = tabFolder.getItem(i);
			if (tempItem.isShowing()) {
				item = tempItem;
			}
		}

		// if we have no visible tabs, abort.
		if (item == null) {
			return new Point(0, 0);
		}

		Rectangle itemBounds = item.getBounds();
		int x = itemBounds.x + itemBounds.width;
		int y = itemBounds.y + itemBounds.height;
		return new Point(x, y);
	}

	/**
	 * Closes the part that's backed by the given widget.
	 *
	 * @param widget the part that owns this widget
	 * @return <tt>true</tt> if the part was closed, <tt>false</tt> otherwise
	 */
	private boolean closePart(Widget widget) {
		MUIElement uiElement = (MUIElement) widget.getData(AbstractPartRenderer.OWNING_ME);
		MPart part = (MPart) ((uiElement instanceof MPart) ? uiElement : ((MPlaceholder) uiElement).getRef());
		if (!isClosable(part)) {
			return false;
		}

		IEclipseContext partContext = part.getContext();
		IEclipseContext parentContext = getContextForParent(part);
		// a part may not have a context if it hasn't been rendered
		IEclipseContext context = partContext == null ? parentContext : partContext;
		// ask user to save if necessary and close part if it is not dirty
		EPartService partService = context.get(EPartService.class);
		if (partService.savePart(part, true)) {
			partService.hidePart(part);
			return true;
		}
		// the user has canceled the save operation, so the part is not closed
		return false;
	}

	@Override
	protected void showTab(MUIElement element) {
		super.showTab(element);

		// an invisible element won't have the correct widget hierarchy
		if (!element.isVisible()) {
			return;
		}

		final CTabFolder tabFolder = (CTabFolder) getParentWidget(element);
		CTabItem tabItem = findItemForPart(element, null);
		if (tabItem == null) {
			createTab(element.getParent(), element);
			tabItem = findItemForPart(element, element.getParent());
		}
		Control ctrl = (Control) element.getWidget();
		if (ctrl != null && ctrl.getParent() != tabFolder) {
			ctrl.setParent(tabFolder);
			tabItem.setControl(ctrl);
		} else if (element.getWidget() == null) {
			Control tabCtrl = (Control) renderer.createGui(element);
			tabItem.setControl(tabCtrl);
		}

		ignoreTabSelChanges = true;
		// Ensure that the newly selected control is correctly sized
		if (tabItem.getControl() instanceof Composite) {
			Composite ctiComp = (Composite) tabItem.getControl();
			// see bug 461573, 528720: call below is still needed to make view
			// descriptions visible after unhiding the view with changed bounds
			ctiComp.requestLayout();
		}
		tabFolder.setSelection(tabItem);
		ignoreTabSelChanges = false;

		// Show the new state
		adjustTopRight(tabFolder);
	}

	/**
	 * @param item
	 */
	protected void showMenu(ToolItem item) {
		MPart part = (MPart) item.getData(THE_PART_KEY);
		if (part == null) {
			return;
		}
		Control ctrl = (Control) part.getWidget();
		MMenu menuModel = getViewMenu(part);
		if (menuModel == null || !menuModel.isToBeRendered())
			return;

		final Menu swtMenu = (Menu) renderer.createGui(menuModel, ctrl.getShell(), part.getContext());
		if (swtMenu == null)
			return;

		ctrl.addDisposeListener(e -> {
			if (!swtMenu.isDisposed()) {
				swtMenu.dispose();
			}
		});

		// ...and Show it...
		Rectangle ib = item.getBounds();
		Point displayAt = item.getParent().toDisplay(ib.x, ib.y + ib.height);
		swtMenu.setLocation(displayAt);
		swtMenu.setVisible(true);

		Display display = swtMenu.getDisplay();
		while (!swtMenu.isDisposed() && swtMenu.isVisible()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		if (!swtMenu.isDisposed() && !(swtMenu.getData() instanceof MenuManager)) {
			swtMenu.dispose();
		}
	}

	private Image getViewMenuImage() {
		if (viewMenuImage == null) {
			viewMenuImage = getImageFromURI(viewMenuURI);
		}
		return viewMenuImage;
	}

	private void openMenuFor(MPart part, CTabFolder folder, Point point) {
		Menu tabMenu = createTabMenu(folder, part);
		tabMenu.setData(STACK_SELECTED_PART, part);
		tabMenu.setLocation(point.x, point.y);
		tabMenu.setVisible(true);
	}

	protected boolean isClosable(MPart part) {
		MPlaceholder curSharedRef = part.getCurSharedRef();
		if (curSharedRef != null) {
			// if it's a shared part check its current ref
			if (curSharedRef.getTags().contains(IPresentationEngine.NO_CLOSE)) {
				return false;
			}
			return curSharedRef.isCloseable();
		}

		return part.isCloseable();
	}

	private Menu createTabMenu(CTabFolder folder, MPart part) {
		Shell shell = folder.getShell();
		Menu cachedMenu = (Menu) shell.getData(SHELL_CLOSE_EDITORS_MENU);
		if (cachedMenu == null) {
			cachedMenu = new Menu(folder);
			shell.setData(SHELL_CLOSE_EDITORS_MENU, cachedMenu);
		} else {
			for (MenuItem item : cachedMenu.getItems()) {
				item.dispose();
			}
		}

		final Menu menu = cachedMenu;
		populateTabMenu(menu, part);
		return menu;
	}

	/**
	 * Populate the tab's context menu for the given part.
	 *
	 * @param menu the menu to be populated
	 * @param part the relevant part
	 */
	protected void populateTabMenu(final Menu menu, MPart part) {

		int closeableElements = 0;
		if (isClosable(part)) {
			createMenuItem(menu, SWTRenderersMessages.menuClose, e -> closePart(menu));
			closeableElements++;
		}

		MElementContainer<MUIElement> parent = getParent(part);
		if (parent != null) {
			closeableElements += getCloseableSiblingParts(part).size();

			if (closeableElements >= 2) {
				createMenuItem(menu, SWTRenderersMessages.menuCloseOthers, e -> closeSiblingParts(menu, true));

				// create menu for parts on the left
				if (!getCloseableSideParts(part, true).isEmpty()) {
					createMenuItem(menu, SWTRenderersMessages.menuCloseLeft, e -> closeSideParts(menu, true));
				}

				// create menu for parts on the right
				if (!getCloseableSideParts(part, false).isEmpty()) {
					createMenuItem(menu, SWTRenderersMessages.menuCloseRight, e -> closeSideParts(menu, false));
				}

				new MenuItem(menu, SWT.SEPARATOR);

				createMenuItem(menu, SWTRenderersMessages.menuCloseAll, e -> closeSiblingParts(menu, false));
			}
		}

		if (isDetachable(part)) {
			if (closeableElements > 0) {
				new MenuItem(menu, SWT.SEPARATOR);
			}

			createMenuItem(menu, SWTRenderersMessages.menuDetach, e -> detachActivePart(menu));
		}
	}

	protected boolean isDetachable(MPart part) {
		// if it's a shared part check its current ref
		if (part.getCurSharedRef() != null) {
			return !part.getCurSharedRef().getTags().contains(IPresentationEngine.NO_DETACH);
		}

		return !part.getTags().contains(IPresentationEngine.NO_DETACH);
	}

	/**
	 *
	 * Detaches the currently selected part
	 *
	 * @param menu
	 */
	private void detachActivePart(final Menu menu) {
		MPart selectedPart = (MPart) menu.getData(STACK_SELECTED_PART);
		CTabItem cti = findItemForPart(selectedPart);
		if (cti == null || cti.getParent() == null) {
			return;
		}
		CTabFolder parent = cti.getParent();

		EModelService modelService = getContextForParent(selectedPart).get(EModelService.class);
		Rectangle bounds = parent.getBounds();
		Point display = parent.toDisplay(bounds.x, bounds.y);
		modelService.detach(selectedPart, display.x, display.y, bounds.width, bounds.height);
	}

	/**
	 *
	 * Closes the currently selected part
	 *
	 * @param menu
	 */
	private void closePart(final Menu menu) {
		MPart selectedPart = (MPart) menu.getData(STACK_SELECTED_PART);
		EPartService partService = getContextForParent(selectedPart).get(EPartService.class);
		if (partService.savePart(selectedPart, true)) {
			partService.hidePart(selectedPart);
		}
	}

	/**
	 * Helper method for creating menu items
	 */
	private MenuItem createMenuItem(final Menu menu, String menuItemText, Consumer<SelectionEvent> c) {
		MenuItem menuItem = new MenuItem(menu, SWT.NONE);
		menuItem.setText(menuItemText);
		menuItem.addSelectionListener(SelectionListener.widgetSelectedAdapter(c));
		return menuItem;

	}

	private MElementContainer<MUIElement> getParent(MPart part) {
		MElementContainer<MUIElement> parent = part.getParent();
		if (parent == null) {
			MPlaceholder placeholder = part.getCurSharedRef();
			return placeholder == null ? null : placeholder.getParent();
		}
		return parent;
	}

	private List<MPart> getCloseableSideParts(MPart part, boolean left) {
		MElementContainer<MUIElement> container = getParent(part);
		if (container == null) {
			return new ArrayList<>();
		}

		int thisPartIdx = getPartIndex(part, container);
		if (thisPartIdx == -1) {
			return new ArrayList<>();
		}
		List<MUIElement> children = container.getChildren();
		final int start = left ? 0 : thisPartIdx + 1;
		final int end = left ? thisPartIdx : children.size();

		return getCloseableSiblingParts(part, children, start, end);
	}

	private int getPartIndex(MPart part, MElementContainer<MUIElement> container) {
		List<MUIElement> children = container.getChildren();
		for (int i = 0; i < children.size(); i++) {
			MUIElement child = children.get(i);
			MPart otherPart = null;
			if (child instanceof MPart) {
				otherPart = (MPart) child;
			} else if (child instanceof MPlaceholder) {
				MUIElement otherItem = ((MPlaceholder) child).getRef();
				if (otherItem instanceof MPart) {
					otherPart = (MPart) otherItem;
				}
			}
			if (otherPart == part) {
				return i;
			}
		}
		return -1;
	}

	private List<MPart> getCloseableSiblingParts(MPart part) {
		MElementContainer<MUIElement> container = getParent(part);
		if (container == null) {
			return new ArrayList<>();
		}

		List<MUIElement> children = container.getChildren();
		return getCloseableSiblingParts(part, children, 0, children.size());
	}

	private List<MPart> getCloseableSiblingParts(MPart part, List<MUIElement> children, final int start,
			final int end) {
		// broken out from closeSiblingParts so it can be used to determine how
		// many closeable siblings are available
		List<MPart> closeableSiblings = new ArrayList<>();
		for (int i = start; i < end; i++) {
			MUIElement child = children.get(i);
			// If the element isn't showing skip it
			if (!child.isToBeRendered())
				continue;

			MPart otherPart = null;
			if (child instanceof MPart)
				otherPart = (MPart) child;
			else if (child instanceof MPlaceholder) {
				MUIElement otherItem = ((MPlaceholder) child).getRef();
				if (otherItem instanceof MPart)
					otherPart = (MPart) otherItem;
			}
			if (otherPart == null)
				continue;

			if (part.equals(otherPart))
				continue; // skip selected item
			if (otherPart.isToBeRendered() && isClosable(otherPart))
				closeableSiblings.add(otherPart);
		}
		return closeableSiblings;
	}

	private void closeSideParts(Menu menu, boolean left) {
		MPart selectedPart = (MPart) menu.getData(STACK_SELECTED_PART);
		MElementContainer<MUIElement> container = getParent(selectedPart);
		if (container == null) {
			return;
		}
		List<MPart> others = getCloseableSideParts(selectedPart, left);
		closeSiblingParts(selectedPart, others, true);
	}

	private void closeSiblingParts(Menu menu, boolean skipThisPart) {
		MPart part = (MPart) menu.getData(STACK_SELECTED_PART);
		MElementContainer<MUIElement> container = getParent(part);
		if (container == null) {
			return;
		}
		List<MPart> others = getCloseableSiblingParts(part);
		closeSiblingParts(part, others, skipThisPart);
	}

	private void closeSiblingParts(MPart part, List<MPart> others, boolean skipThisPart) {
		MElementContainer<MUIElement> container = getParent(part);

		// add the current part last so that we unrender obscured items first
		if (!skipThisPart && part.isToBeRendered() && isClosable(part)) {
			others.add(part);
		}

		// add the selected element of the stack at the end, else we may end up
		// selecting another part when we hide it since it is the selected
		// element
		MUIElement selectedElement = container.getSelectedElement();
		if (others.remove(selectedElement)) {
			others.add((MPart) selectedElement);
		} else if (selectedElement instanceof MPlaceholder) {
			selectedElement = ((MPlaceholder) selectedElement).getRef();
			if (others.remove(selectedElement)) {
				others.add((MPart) selectedElement);
			}
		}

		EPartService partService = getContextForParent(part).get(EPartService.class);
		// try using the ISaveHandler first... This gives better control of
		// dialogs...
		ISaveHandler saveHandler = getContextForParent(part).get(ISaveHandler.class);
		if (saveHandler != null) {
			final List<MPart> toPrompt = new ArrayList<>(others);
			toPrompt.retainAll(partService.getDirtyParts());

			boolean cancel = false;
			if (toPrompt.size() > 1) {
				cancel = !saveHandler.saveParts(toPrompt, true);
			} else if (toPrompt.size() == 1) {
				cancel = !saveHandler.save(toPrompt.get(0), true);
			}
			if (cancel) {
				return;
			}

			for (MPart other : others) {
				partService.hidePart(other);
			}
			return;
		}

		// No ISaveHandler, fall back to just using the part service...
		for (MPart otherPart : others) {
			if (partService.savePart(otherPart, true))
				partService.hidePart(otherPart);
		}
	}

	public static MMenu getViewMenu(MPart part) {
		if (part == null || part.getMenus() == null) {
			return null;
		}
		for (MMenu menu : part.getMenus()) {
			if (menu.getTags().contains(TAG_VIEW_MENU)) {
				return menu;
			}
		}
		return null;
	}

	/**
	 * Determine whether the given view menu has any visible menu items.
	 *
	 * @param viewMenu the view menu to check
	 * @param part     the view menu's parent part
	 * @return <tt>true</tt> if the specified view menu has visible children,
	 *         <tt>false</tt> otherwise
	 */
	private boolean hasVisibleMenuItems(MMenu viewMenu, MPart part) {
		if (!viewMenu.isToBeRendered() || !viewMenu.isVisible()) {
			return false;
		}

		for (MMenuElement menuElement : viewMenu.getChildren()) {
			if (menuElement.isToBeRendered() && menuElement.isVisible()) {
				if (OpaqueElementUtil.isOpaqueMenuItem(menuElement)
						|| OpaqueElementUtil.isOpaqueMenuSeparator(menuElement)) {
					IContributionItem item = (IContributionItem) OpaqueElementUtil.getOpaqueItem(menuElement);
					if (item != null && item.isVisible()) {
						return true;
					}
				} else {
					return true;
				}
			}
		}

		Object menuRenderer = viewMenu.getRenderer();
		if (menuRenderer instanceof MenuManagerRenderer) {
			MenuManager manager = ((MenuManagerRenderer) menuRenderer).getManager(viewMenu);
			if (manager != null && manager.isVisible()) {
				return true;
			}
		}

		Control control = (Control) part.getWidget();
		if (control != null) {
			Menu menu = (Menu) renderer.createGui(viewMenu, control.getShell(), part.getContext());
			if (menu != null) {
				menuRenderer = viewMenu.getRenderer();
				if (menuRenderer instanceof MenuManagerRenderer) {
					MenuManagerRenderer menuManagerRenderer = (MenuManagerRenderer) menuRenderer;
					MenuManager manager = menuManagerRenderer.getManager(viewMenu);
					if (manager != null) {
						// remark ourselves as dirty so that the menu will be
						// reconstructed
						manager.markDirty();
					}
				}
				return menu.getItemCount() != 0;
			}
		}
		return false;
	}

	/**
	 * An event handler for listening to changes to the children of an element
	 * container. The tab folder may need to layout itself again if a part's toolbar
	 * has been changed.
	 */
	@SuppressWarnings("javadoc")
	public class TabStateHandler implements EventHandler {

		@SuppressWarnings("restriction")
		@Override
		public void handleEvent(Event event) {
			Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
			Object newValue = event.getProperty(UIEvents.EventTags.NEW_VALUE);
			Object oldValue = event.getProperty(UIEvents.EventTags.OLD_VALUE);

			if (!validateElement(element) || !validateValues(oldValue, newValue)) {
				return;
			}

			MPart part = newValue instanceof MPlaceholder ? (MPart) ((MPlaceholder) newValue).getRef()
					: (MPart) element;
			CTabItem cti = findItemForPart(part);
			if (cti == null) {
				return;
			}

			boolean isCssEngineActive = isCssEngineActive(cti);
			boolean isSelectedTab = cti == cti.getParent().getSelection();
			boolean partActivatedEvent = newValue instanceof MPlaceholder;

			if (CSSConstants.CSS_CONTENT_CHANGE_CLASS.equals(newValue)) {
				part.getTags().remove(CSSConstants.CSS_CONTENT_CHANGE_CLASS);
				if (!isSelectedTab) {
					addHighlight(part, cti, isCssEngineActive);
				}
			} else if (partActivatedEvent && part.getTags().contains(CSSConstants.CSS_HIGHLIGHTED_CLASS)) {
				removeHighlight(part, cti, isCssEngineActive);
			}

			String prevCssCls = WidgetElement.getCSSClass(cti);
			setCSSInfo(part, cti);

			if (prevCssCls == null || !prevCssCls.equals(WidgetElement.getCSSClass(cti))) {
				reapplyStyles(cti.getParent());
			}

			// Only update tab busy state if the CSS engine is not active
			if (isCssEngineActive || partActivatedEvent) {
				return;
			}

			updateBusyStateNoCss(cti, newValue, oldValue);
		}

		public boolean validateElement(Object element) {
			return element instanceof MPart || element instanceof MPartStack;
		}

		public boolean validateValues(Object oldValue, Object newValue) {
			return newValue instanceof MPlaceholder
					// part gets active
					|| isTagAdded(CSSConstants.CSS_BUSY_CLASS, oldValue, newValue)
					// part gets busy
					|| isTagRemoved(CSSConstants.CSS_BUSY_CLASS, oldValue, newValue)
					// part gets idle
					|| isTagAdded(CSSConstants.CSS_CONTENT_CHANGE_CLASS, oldValue, newValue);
			// content of part changed
		}

		private boolean isTagAdded(String tagName, Object oldValue, Object newValue) {
			return oldValue == null && tagName.equals(newValue);
		}

		private boolean isTagRemoved(String tagName, Object oldValue, Object newValue) {
			return newValue == null && tagName.equals(oldValue);
		}
	}

	@SuppressWarnings("restriction")
	static boolean isCssEngineActive(CTabItem cti) {
		return WidgetElement.getEngine(cti.getParent()) != null;
	}

	static void removeHighlight(MPart part, CTabItem cti, boolean cssEngineActive) {
		part.getTags().remove(CSSConstants.CSS_HIGHLIGHTED_CLASS);
		if (!cssEngineActive) {
			cti.setFont(JFaceResources.getFontRegistry().get(TAB_FONT_KEY));
		}
	}

	static void addHighlight(MPart part, CTabItem cti, boolean cssEngineActive) {
		part.getTags().add(CSSConstants.CSS_HIGHLIGHTED_CLASS);
		if (!cssEngineActive) {
			cti.setFont(JFaceResources.getFontRegistry().getBold(TAB_FONT_KEY));
		}
	}

	/**
	 * Updates the visual for busy state of the part tab in case CSS engine is not
	 * active
	 */
	static void updateBusyStateNoCss(CTabItem cti, Object newValue, Object oldValue) {
		Font updatedFont = null;
		if (CSSConstants.CSS_BUSY_CLASS.equals(newValue)) {
			updatedFont = JFaceResources.getFontRegistry().getItalic(TAB_FONT_KEY);
		} else if (CSSConstants.CSS_BUSY_CLASS.equals(oldValue)) {
			updatedFont = JFaceResources.getFontRegistry().get(TAB_FONT_KEY);
		}
		if (updatedFont != null) {
			cti.setFont(updatedFont);
		}
	}

	@Override
	protected boolean imageChanged() {
		return this.imageChanged;
	}
}
