/*******************************************************************************
 * Copyright (c) 2000, 2021 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
 *     Guy Gurfinkel, guy.g@zend.com - [content assist][api] provide better access to ContentAssistant - https://bugs.eclipse.org/bugs/show_bug.cgi?id=169954
 *     Anton Leherbauer (Wind River Systems) - [content assist][api] ContentAssistEvent should contain information about auto activation - https://bugs.eclipse.org/bugs/show_bug.cgi?id=193728
 *     Marcel Bruch, bruch@cs.tu-darmstadt.de - [content assist] Allow to re-sort proposals - https://bugs.eclipse.org/bugs/show_bug.cgi?id=350991
 *     John Glassmyer, jogl@google.com - catch Content Assist exceptions to protect navigation keys - http://bugs.eclipse.org/434901
 *     Mickael Istria (Red Hat Inc.) - [251156] Allow multiple contentAssitProviders internally & inheritance
 *     Christoph Läubrich - Bug 508821 - [Content assist] More flexible API in IContentAssistProcessor to decide whether to auto-activate or not
 *     						Bug 570459 - [genericeditor] Support ContentAssistProcessors to be registered as OSGi-Services
 *******************************************************************************/
package org.eclipse.jface.text.contentassist;

import static org.eclipse.jface.util.Util.isValid;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.custom.VerifyKeyListener;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.graphics.Color;
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.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Monitor;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Widget;

import org.eclipse.core.commands.IHandler;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;

import org.eclipse.jface.bindings.keys.KeySequence;
import org.eclipse.jface.contentassist.IContentAssistSubjectControl;
import org.eclipse.jface.contentassist.ISubjectControlContentAssistProcessor;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.preference.JFacePreferences;
import org.eclipse.jface.util.Geometry;
import org.eclipse.jface.util.OpenStrategy;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.IEventConsumer;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.IViewportListener;
import org.eclipse.jface.text.IWidgetTokenKeeper;
import org.eclipse.jface.text.IWidgetTokenKeeperExtension;
import org.eclipse.jface.text.IWidgetTokenOwner;
import org.eclipse.jface.text.IWidgetTokenOwnerExtension;
import org.eclipse.jface.text.TextUtilities;


/**
 * The standard implementation of the {@link IContentAssistant} interface. Usually, clients
 * instantiate this class and configure it before using it.
 *
 * Since 3.12, it can compute and display the proposals asynchronously when invoking
 * {@link #ContentAssistant(boolean)} with <code>true</code>.
 */
public class ContentAssistant implements IContentAssistant, IContentAssistantExtension, IContentAssistantExtension2, IContentAssistantExtension3, IContentAssistantExtension4, IWidgetTokenKeeper, IWidgetTokenKeeperExtension {



	/**
	 * Content assist command identifier for 'select next proposal'.
	 *
	 * @since 3.4
	 */
	public static final String SELECT_NEXT_PROPOSAL_COMMAND_ID= "org.eclipse.ui.edit.text.contentAssist.selectNextProposal"; //$NON-NLS-1$
	/**
	 * Content assist command identifier for 'select previous proposal'.
	 *
	 * @since 3.4
	 */
	public static final String SELECT_PREVIOUS_PROPOSAL_COMMAND_ID= "org.eclipse.ui.edit.text.contentAssist.selectPreviousProposal"; //$NON-NLS-1$

	enum TriggerType {
		CONTEXT_INFORMATION,
		COMPLETION_PROPOSAL, NONE;
	}

	/**
	 * A generic closer class used to monitor various interface events in order to determine whether
	 * content-assist should be terminated and all associated windows closed.
	 */
	class Closer implements ControlListener, MouseListener, FocusListener, DisposeListener, IViewportListener {

		/** The shell that a <code>ControlListener</code> is registered with. */
		private Shell fShell;
		/**
		 * The control that a <code>MouseListener</code>, a<code>FocusListener</code> and a
		 * <code>DisposeListener</code> are registered with.
		 */
		private Control fControl;

		/**
		 * Installs this closer on it's viewer's text widget.
		 */
		protected void install() {
			Control control= fContentAssistSubjectControlAdapter.getControl();
			fControl= control;
			if (isValid(control)) {

				Shell shell= control.getShell();
				fShell= shell;
				shell.addControlListener(this);

				control.addMouseListener(this);
				control.addFocusListener(this);

				/*
				 * 1GGYYWK: ITPJUI:ALL - Dismissing editor with code assist up causes lots of
				 * Internal Errors
				 */
				control.addDisposeListener(this);
			}
			if (fViewer != null)
				fViewer.addViewportListener(this);
		}

		/**
		 * Uninstalls this closer from the viewer's text widget.
		 */
		protected void uninstall() {
			Control shell= fShell;
			fShell= null;
			if (isValid(shell))
				shell.removeControlListener(this);

			Control control= fControl;
			fControl= null;
			if (isValid(control)) {

				control.removeMouseListener(this);
				control.removeFocusListener(this);

				/*
				 * 1GGYYWK: ITPJUI:ALL - Dismissing editor with code assist up causes lots of
				 * Internal Errors
				 */
				control.removeDisposeListener(this);
			}

			if (fViewer != null)
				fViewer.removeViewportListener(this);
		}

		@Override
		public void controlResized(ControlEvent e) {
			hide();
		}

		@Override
		public void controlMoved(ControlEvent e) {
			hide();
		}

		@Override
		public void mouseDown(MouseEvent e) {
			hide();
		}

		@Override
		public void mouseUp(MouseEvent e) {
		}

		@Override
		public void mouseDoubleClick(MouseEvent e) {
			hide();
		}

		@Override
		public void focusGained(FocusEvent e) {
		}

		@Override
		public void focusLost(FocusEvent e) {
			Control control= fControl;
			if (isValid(control)) {
				Display d= control.getDisplay();
				if (d != null) {
					d.asyncExec(() -> {
						if (!fProposalPopup.hasFocus() && (fContextInfoPopup == null || !fContextInfoPopup.hasFocus()))
							hide();
					});
				}
			}
		}

		/*
		 * @seeDisposeListener#widgetDisposed(DisposeEvent)
		 */
		@Override
		public void widgetDisposed(DisposeEvent e) {
			/*
			 * 1GGYYWK: ITPJUI:ALL - Dismissing editor with code assist up causes lots of Internal
			 * Errors
			 */
			hide();
		}

		@Override
		public void viewportChanged(int topIndex) {
			hide();
		}
	}

	/**
	 * An implementation of <code>IContentAssistListener</code>, this class is used to monitor
	 * key events in support of automatic activation of the content assistant. If enabled, the
	 * implementation utilizes a thread to watch for input characters matching the activation
	 * characters specified by the content assist processor, and if detected, will wait the
	 * indicated delay interval before activating the content assistant.
	 *
	 * @since 3.4 protected, was added in 2.1 as private class
	 */
	protected class AutoAssistListener extends KeyAdapter implements Runnable, VerifyKeyListener {

		private Thread fThread;
		private boolean fIsReset= false;
		private Object fMutex= new Object();
		private int fShowStyle;

		private final static int SHOW_PROPOSALS= 1;
		private final static int SHOW_CONTEXT_INFO= 2;

		protected AutoAssistListener() {
		}

		protected void start(int showStyle) {
			fShowStyle= showStyle;
			fThread= new Thread(this, JFaceTextMessages.getString("ContentAssistant.assist_delay_timer_name")); //$NON-NLS-1$
			fThread.start();
		}

		@Override
		public void run() {
			try {
				while (true) {
					synchronized (fMutex) {
						if (fAutoActivationDelay != 0)
							fMutex.wait(fAutoActivationDelay);
						if (fIsReset) {
							fIsReset= false;
							continue;
						}
					}
					showAssist(fShowStyle);
					break;
				}
			} catch (InterruptedException e) {
			}
			fThread= null;
		}

		protected void reset(int showStyle) {
			synchronized (fMutex) {
				fShowStyle= showStyle;
				fIsReset= true;
				fMutex.notifyAll();
			}
		}

		protected void stop() {
			Thread threadToStop= fThread;
			if (threadToStop != null && threadToStop.isAlive())
				threadToStop.interrupt();
		}

		@Override
		public void keyPressed(KeyEvent e) {
			// Only act on typed characters and ignore modifier-only events
			if (e.character == 0 && (e.keyCode & SWT.KEYCODE_BIT) == 0)
				return;

			if (e.character != 0 && (e.stateMask == SWT.ALT))
				return;

			TriggerType triggerType= getAutoActivationTriggerType(e.character);

			// Only act on characters that are trigger candidates. This
			// avoids computing the model selection on every keystroke
			if (triggerType == TriggerType.NONE) {
				stop();
				return;
			}

			int showStyle;
			if (triggerType == TriggerType.COMPLETION_PROPOSAL && !isProposalPopupActive())
				showStyle= SHOW_PROPOSALS;
			else {
				if (triggerType == TriggerType.CONTEXT_INFORMATION && !isContextInfoPopupActive())
					showStyle= SHOW_CONTEXT_INFO;
				else {
					stop();
					return;
				}
			}

			if (fThread != null && fThread.isAlive())
				reset(showStyle);
			else
				start(showStyle);
		}

		@Override
		public void verifyKey(VerifyEvent event) {
			keyPressed(event);
		}

		protected void showAssist(final int showStyle) {
			if (fContentAssistSubjectControlAdapter == null)
				return;
			final Control control= fContentAssistSubjectControlAdapter.getControl();
			if (control == null)
				return;

			final Display d= control.getDisplay();
			if (d == null)
				return;

			try {
				d.syncExec(() -> {
					if (isProposalPopupActive())
						return;

					if (control.isDisposed() || !control.isFocusControl())
						return;

					if (showStyle == SHOW_PROPOSALS) {
						if (!prepareToShowCompletions(true))
							return;
						fProposalPopup.showProposals(true);
						fLastAutoActivation= System.currentTimeMillis();
					} else if (showStyle == SHOW_CONTEXT_INFO && fContextInfoPopup != null) {
						promoteKeyListener();
						fContextInfoPopup.showContextProposals(true);
					}
				});
			} catch (SWTError e) {
			}
		}
	}

	/**
	 * The layout manager layouts the various windows associated with the content assistant based on
	 * the settings of the content assistant.
	 */
	class LayoutManager implements Listener {

		// Presentation types.
		/** The presentation type for the proposal selection popup. */
		public final static int LAYOUT_PROPOSAL_SELECTOR= 0;
		/** The presentation type for the context selection popup. */
		public final static int LAYOUT_CONTEXT_SELECTOR= 1;
		/** The presentation type for the context information hover . */
		public final static int LAYOUT_CONTEXT_INFO_POPUP= 2;

		int fContextType= LAYOUT_CONTEXT_SELECTOR;
		Shell[] fShells= new Shell[3];
		Object[] fPopups= new Object[3];

		protected void add(Object popup, Shell shell, int type, int offset) {
			Assert.isNotNull(popup);
			Assert.isTrue(shell != null && !shell.isDisposed());
			checkType(type);

			if (fShells[type] != shell) {
				if (fShells[type] != null)
					fShells[type].removeListener(SWT.Dispose, this);
				shell.addListener(SWT.Dispose, this);
				fShells[type]= shell;
			}

			fPopups[type]= popup;
			if (type == LAYOUT_CONTEXT_SELECTOR || type == LAYOUT_CONTEXT_INFO_POPUP)
				fContextType= type;

			layout(type, offset);
			adjustListeners(type);
		}

		protected void checkType(int type) {
			Assert.isTrue(type == LAYOUT_PROPOSAL_SELECTOR ||
				type == LAYOUT_CONTEXT_SELECTOR || type == LAYOUT_CONTEXT_INFO_POPUP);
		}

		@Override
		public void handleEvent(Event event) {
			Widget source= event.widget;
			source.removeListener(SWT.Dispose, this);

			int type= getShellType(source);
			checkType(type);
			fShells[type]= null;

			switch (type) {
				case LAYOUT_PROPOSAL_SELECTOR:
					if (fContextType == LAYOUT_CONTEXT_SELECTOR &&
							isValid(fShells[LAYOUT_CONTEXT_SELECTOR])) {
						// Restore event notification to the tip popup.
						addContentAssistListener((IContentAssistListener) fPopups[LAYOUT_CONTEXT_SELECTOR], CONTEXT_SELECTOR);
					}
					break;

				case LAYOUT_CONTEXT_SELECTOR:
					if (isValid(fShells[LAYOUT_PROPOSAL_SELECTOR])) {
						if (fProposalPopupOrientation == PROPOSAL_STACKED)
							layout(LAYOUT_PROPOSAL_SELECTOR, getSelectionOffset());
						// Restore event notification to the proposal popup.
						addContentAssistListener((IContentAssistListener) fPopups[LAYOUT_PROPOSAL_SELECTOR], PROPOSAL_SELECTOR);
					}
					fContextType= LAYOUT_CONTEXT_INFO_POPUP;
					break;

				case LAYOUT_CONTEXT_INFO_POPUP:
					if (isValid(fShells[LAYOUT_PROPOSAL_SELECTOR])) {
						if (fContextInfoPopupOrientation == CONTEXT_INFO_BELOW)
							layout(LAYOUT_PROPOSAL_SELECTOR, getSelectionOffset());
					}
					fContextType= LAYOUT_CONTEXT_SELECTOR;
					break;
			}
		}

		protected int getShellType(Widget shell) {
			for (int i= 0; i < fShells.length; i++) {
				if (fShells[i] == shell)
					return i;
			}
			return -1;
		}

		/**
		 * Layouts the popup defined by <code>type</code> at the given widget offset.
		 *
		 * @param type the kind of popup to layout
		 * @param offset the widget offset
		 */
		protected void layout(int type, int offset) {
			switch (type) {
				case LAYOUT_PROPOSAL_SELECTOR:
					layoutProposalSelector(offset);
					break;
				case LAYOUT_CONTEXT_SELECTOR:
					layoutContextSelector(offset);
					break;
				case LAYOUT_CONTEXT_INFO_POPUP:
					layoutContextInfoPopup(offset);
					break;
			}
		}

		protected void layoutProposalSelector(int offset) {
			if (fContextType == LAYOUT_CONTEXT_INFO_POPUP &&
					fContextInfoPopupOrientation == CONTEXT_INFO_BELOW &&
					isValid(fShells[LAYOUT_CONTEXT_INFO_POPUP])) {
				// Stack proposal selector beneath the tip box.
				Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
				Shell parent= fShells[LAYOUT_CONTEXT_INFO_POPUP];
				shell.setLocation(getStackedLocation(shell, parent));
			} else if (fContextType != LAYOUT_CONTEXT_SELECTOR ||
					!isValid(fShells[LAYOUT_CONTEXT_SELECTOR])) {
				// There are no other presentations to be concerned with,
				// so place the proposal selector beneath the cursor line.
				Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
				CompletionProposalPopup popup= (CompletionProposalPopup) fPopups[LAYOUT_PROPOSAL_SELECTOR];
				shell.setBounds(computeBoundsBelowAbove(shell, shell.getSize(), offset, popup));
			} else {
				CompletionProposalPopup popup= ((CompletionProposalPopup) fPopups[LAYOUT_PROPOSAL_SELECTOR]);
				switch (fProposalPopupOrientation) {
					case PROPOSAL_REMOVE: {
						// Remove the tip selector and place the
						// proposal selector beneath the cursor line.
						fShells[LAYOUT_CONTEXT_SELECTOR].dispose();
						Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
						shell.setBounds(computeBoundsBelowAbove(shell, shell.getSize(), offset, popup));
						break;
					}
					case PROPOSAL_OVERLAY: {
						// Overlay the tip selector with the proposal selector.
						Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
						shell.setBounds(computeBoundsBelowAbove(shell, shell.getSize(), offset, popup));
						break;
					}
					case PROPOSAL_STACKED: {
						// Stack the proposal selector beneath the tip selector.
						Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
						Shell parent= fShells[LAYOUT_CONTEXT_SELECTOR];
						shell.setLocation(getStackedLocation(shell, parent));
						break;
					}
				}
			}
		}

		protected void layoutContextSelector(int offset) {
			// Always place the context selector beneath the cursor line.
			Shell shell= fShells[LAYOUT_CONTEXT_SELECTOR];
			shell.setBounds(computeBoundsBelowAbove(shell, shell.getSize(), offset, null));

			if (isValid(fShells[LAYOUT_PROPOSAL_SELECTOR])) {
				switch (fProposalPopupOrientation) {
					case PROPOSAL_REMOVE:
						// Remove the proposal selector.
						fShells[LAYOUT_PROPOSAL_SELECTOR].dispose();
						break;

					case PROPOSAL_OVERLAY:
						// The proposal selector has been overlaid by the tip selector.
						break;

					case PROPOSAL_STACKED: {
						// Stack the proposal selector beneath the tip selector.
						shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
						Shell parent= fShells[LAYOUT_CONTEXT_SELECTOR];
						shell.setLocation(getStackedLocation(shell, parent));
						break;
					}
				}
			}
		}

		protected void layoutContextInfoPopup(int offset) {
			switch (fContextInfoPopupOrientation) {
				case CONTEXT_INFO_ABOVE: {
					// Place the popup above the cursor line.
					Shell shell= fShells[LAYOUT_CONTEXT_INFO_POPUP];
					shell.setBounds(computeBoundsAboveBelow(shell, shell.getSize(), offset));
					break;
				}
				case CONTEXT_INFO_BELOW: {
					// Place the popup beneath the cursor line.
					Shell parent= fShells[LAYOUT_CONTEXT_INFO_POPUP];
					parent.setBounds(computeBoundsBelowAbove(parent, parent.getSize(), offset, null));
					if (isValid(fShells[LAYOUT_PROPOSAL_SELECTOR])) {
						// Stack the proposal selector beneath the context info popup.
						Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
						shell.setLocation(getStackedLocation(shell, parent));
					}
					break;
				}
			}
		}

		/**
		 * Moves <code>point</code> such that <code>rectangle</code> does not bleed outside of
		 * <code>bounds</code>. All coordinates must have the same reference.
		 *
		 * @param point the point to move if needed
		 * @param shellSize the size of the shell that may be moved
		 * @param bounds the bounds
		 * @since 3.3
		 */
		protected void constrainLocation(Point point, Point shellSize, Rectangle bounds) {
			if (point.x + shellSize.x > bounds.x + bounds.width)
				point.x= bounds.x + bounds.width - shellSize.x;

			if (point.x < bounds.x)
				point.x= bounds.x;

			if (point.y + shellSize.y > bounds.y + bounds.height)
				point.y= bounds.y + bounds.height - shellSize.y;

			if (point.y < bounds.y)
				point.y= bounds.y;
		}

		protected Rectangle constrainHorizontally(Rectangle rect, Rectangle bounds) {
			// clip width
			if (rect.width > bounds.width)
				rect.width= bounds.width;

			if (rect.x + rect.width > bounds.x + bounds.width)
				rect.x= bounds.x + bounds.width - rect.width;
			if (rect.x < bounds.x)
				rect.x= bounds.x;

			return rect;
		}

		/**
		 * Returns the display bounds for <code>shell</code> such that it appears right above
		 * <code>offset</code>, or below it if above is not suitable. The returned bounds lie
		 * within the monitor at the caret location and never overlap with the caret line.
		 *
		 * @param shell the shell to compute the placement for
		 * @param preferred the preferred size for <code>shell</code>
		 * @param offset the caret offset in the subject control
		 * @return the point right above <code>offset</code> in display coordinates
		 * @since 3.3
		 */
		protected Rectangle computeBoundsAboveBelow(Shell shell, Point preferred, int offset) {
			Control subjectControl= fContentAssistSubjectControlAdapter.getControl();
			Display display= subjectControl.getDisplay();
			Rectangle caret= getCaretRectangle(offset);
			Monitor monitor= getClosestMonitor(display, caret);
			Rectangle bounds= monitor.getClientArea();
			Geometry.moveInside(caret, bounds);

			int spaceAbove= caret.y - bounds.y;
			int caretLowerY= caret.y + caret.height;
			int spaceBelow= bounds.y + bounds.height - caretLowerY;
			Rectangle rect;
			if (spaceAbove >= preferred.y)
				rect= new Rectangle(caret.x, caret.y - preferred.y, preferred.x, preferred.y);
			else if (spaceBelow >= preferred.y)
				rect= new Rectangle(caret.x, caretLowerY, preferred.x, preferred.y);
			// we can't fit in the preferred size - squeeze into larger area
			else if (spaceBelow <= spaceAbove)
				rect= new Rectangle(caret.x, bounds.y, preferred.x, spaceAbove);
			else
				rect= new Rectangle(caret.x, caretLowerY, preferred.x, spaceBelow);

			return constrainHorizontally(rect, bounds);
		}

		/**
		 * Returns the display bounds for <code>shell</code> such that it appears right below
		 * <code>offset</code>, or above it if below is not suitable. The returned bounds lie
		 * within the monitor at the caret location and never overlap with the caret line.
		 *
		 * @param shell the shell to compute the placement for
		 * @param preferred the preferred size for <code>shell</code>
		 * @param offset the caret offset in the subject control
		 * @param popup a popup to inform if the location was switched to above, <code>null</code> to do nothing
		 * @return the point right below <code>offset</code> in display coordinates
		 * @since 3.3
		 */
		protected Rectangle computeBoundsBelowAbove(Shell shell, Point preferred, int offset, CompletionProposalPopup popup) {
			Control subjectControl= fContentAssistSubjectControlAdapter.getControl();
			Display display= subjectControl.getDisplay();
			Rectangle caret= getCaretRectangle(offset);
			Monitor monitor= getClosestMonitor(display, caret);
			Rectangle bounds= monitor.getClientArea();
			Geometry.moveInside(caret, bounds);

			int threshold= popup == null ? Integer.MAX_VALUE : popup.getMinimalHeight();
			int spaceAbove= caret.y - bounds.y;
			int spaceBelow= bounds.y + bounds.height - (caret.y + caret.height);
			Rectangle rect;
			boolean switched= false;
			if (spaceBelow >= preferred.y)
				rect= new Rectangle(caret.x, caret.y + caret.height, preferred.x, preferred.y);
			// squeeze in below if we have at least threshold space
			else if (spaceBelow >= threshold)
				rect= new Rectangle(caret.x, caret.y + caret.height, preferred.x, spaceBelow);
			else if (spaceAbove >= preferred.y) {
				rect= new Rectangle(caret.x, caret.y - preferred.y, preferred.x, preferred.y);
				switched= true;
			} else if (spaceBelow >= spaceAbove) {
				// we can't fit in the preferred size - squeeze into larger area
				rect= new Rectangle(caret.x, caret.y + caret.height, preferred.x, spaceBelow);
			} else {
				rect= new Rectangle(caret.x, bounds.y, preferred.x, spaceAbove);
				switched= true;
			}

			if (popup != null)
				popup.switchedPositionToAbove(switched);

			return constrainHorizontally(rect, bounds);
		}

		private Rectangle getCaretRectangle(int offset) {
			Point location= fContentAssistSubjectControlAdapter.getLocationAtOffset(offset);
			Control subjectControl= fContentAssistSubjectControlAdapter.getControl();
			Point controlSize= subjectControl.getSize();
			constrainLocation(location, new Point(0, 0), new Rectangle(0, 0, controlSize.x, controlSize.y));
			location= subjectControl.toDisplay(location);
			Rectangle subjectRectangle= new Rectangle(location.x, location.y, 1, fContentAssistSubjectControlAdapter.getLineHeight());
			return subjectRectangle;
		}

		protected Point getStackedLocation(Shell shell, Shell parent) {
			Point p= parent.getLocation();
			Point size= parent.getSize();
			p.x += size.x / 4;
			p.y += size.y;

			p= parent.toDisplay(p);

			Point shellSize= shell.getSize();
			Monitor monitor= getClosestMonitor(parent.getDisplay(), new Rectangle(p.x, p.y, 0, 0));
			Rectangle displayBounds= monitor.getClientArea();
			constrainLocation(p, shellSize, displayBounds);

			return p;
		}

		protected void adjustListeners(int type) {
			switch (type) {
				case LAYOUT_PROPOSAL_SELECTOR:
					if (fContextType == LAYOUT_CONTEXT_SELECTOR &&
							isValid(fShells[LAYOUT_CONTEXT_SELECTOR]))
						// Disable event notification to the tip selector.
						removeContentAssistListener((IContentAssistListener) fPopups[LAYOUT_CONTEXT_SELECTOR], CONTEXT_SELECTOR);
					break;
				case LAYOUT_CONTEXT_SELECTOR:
					if (isValid(fShells[LAYOUT_PROPOSAL_SELECTOR]))
						// Disable event notification to the proposal selector.
						removeContentAssistListener((IContentAssistListener) fPopups[LAYOUT_PROPOSAL_SELECTOR], PROPOSAL_SELECTOR);
					break;
				case LAYOUT_CONTEXT_INFO_POPUP:
					break;
			}
		}

		/**
		 * Copied from org.eclipse.jface.window.Window. Returns the monitor whose client area
		 * contains the given point. If no monitor contains the point, returns the monitor that is
		 * closest to the point. If this is ever made public, it should be moved into a separate
		 * utility class.
		 *
		 * @param toSearch point to find (display coordinates)
		 * @param rectangle rectangle to find (display coordinates)
		 * @return the monitor closest to the given point
		 * @since 3.3
		 */
		private Monitor getClosestMonitor(Display toSearch, Rectangle rectangle) {
			int closest = Integer.MAX_VALUE;

			Point toFind= Geometry.centerPoint(rectangle);
			Monitor[] monitors = toSearch.getMonitors();
			Monitor result = monitors[0];

			for (Monitor current : monitors) {
				Rectangle clientArea = current.getClientArea();

				if (clientArea.contains(toFind)) {
					return current;
				}

				int distance = Geometry.distanceSquared(Geometry.centerPoint(clientArea), toFind);
				if (distance < closest) {
					closest = distance;
					result = current;
				}
			}

			return result;
		}
	}

	/**
	 * Internal key listener and event consumer.
	 */
	class InternalListener implements VerifyKeyListener, IEventConsumer {

		/**
		 * Verifies key events by notifying the registered listeners. Each listener is allowed to
		 * indicate that the event has been handled and should not be further processed.
		 *
		 * @param e the verify event
		 * @see VerifyKeyListener#verifyKey(org.eclipse.swt.events.VerifyEvent)
		 */
		@Override
		public void verifyKey(VerifyEvent e) {
			IContentAssistListener[] listeners= fListeners.clone();
			for (IContentAssistListener listener : listeners) {
				if (listener != null) {
					if (!listener.verifyKey(e) || !e.doit) {
						break;
					}
				}
			}
			if (fAutoAssistListener != null)
				fAutoAssistListener.keyPressed(e);
		}

		/*
		 * @see IEventConsumer#processEvent
		 */
		@Override
		public void processEvent(VerifyEvent event) {

			installKeyListener();

			IContentAssistListener[] listeners= fListeners.clone();
			for (IContentAssistListener listener : listeners) {
				if (listener != null) {
					listener.processEvent(event);
					if (!event.doit)
						return;
				}
			}
		}
	}

	/**
	 * A subclass of ISafeRunnable which, in case of exception, logs a specified error message to the jface.text log and
	 * sets fLastErrorMessage to this message.
	 */
	private abstract class ExceptionLoggingSafeRunnable implements ISafeRunnable {
		private static final String PLUGIN_ID= "org.eclipse.jface.text"; //$NON-NLS-1$

		private final String fMessageKey;

		/**
		 * @param messageKey key passed to JFaceTextMessages to lookup the text of the error message
		 */
		ExceptionLoggingSafeRunnable(String messageKey) {
			fMessageKey= messageKey;
		}

		@Override
		public void handleException(Throwable exception) {
			String message= JFaceTextMessages.getString(fMessageKey);

			IStatus status= new Status(IStatus.ERROR, PLUGIN_ID, message, exception);
			Platform.getLog(Platform.getBundle(PLUGIN_ID)).log(status);

			fLastErrorMessage= message;
		}
	}

	/**
	 * Dialog store constant for the x-size of the completion proposal pop-up
	 *
	 * @since 3.0
	 */
	public static final String STORE_SIZE_X= "size.x"; //$NON-NLS-1$

	/**
	 * Dialog store constant for the y-size of the completion proposal pop-up
	 *
	 * @since 3.0
	 */
	public static final String STORE_SIZE_Y= "size.y"; //$NON-NLS-1$

	/**
	 * Dialog store constant for the x-size of the context selector pop-up
	 *
	 * @since 3.9
	 */
	public static final String STORE_CONTEXT_SELECTOR_POPUP_SIZE_X= "contextSelector.size.x"; //$NON-NLS-1$

	/**
	 * Dialog store constant for the y-size of the context selector pop-up
	 *
	 * @since 3.9
	 */
	public static final String STORE_CONTEXT_SELECTOR_POPUP_SIZE_Y= "contextSelector.size.y"; //$NON-NLS-1$


	// Content-Assist Listener types
	final static int CONTEXT_SELECTOR= 0;
	final static int PROPOSAL_SELECTOR= 1;
	final static int CONTEXT_INFO_POPUP= 2;

	/**
	 * The popup priority: &gt; linked position proposals and hover pop-ups. Default value:
	 * <code>20</code>;
	 *
	 * @since 3.0
	 */
	public static final int WIDGET_PRIORITY= 20;
	private static final int DEFAULT_AUTO_ACTIVATION_DELAY= 500;

	private static final String COMPLETION_ERROR_MESSAGE_KEY= "ContentAssistant.error_computing_completion"; //$NON-NLS-1$
	private static final String CONTEXT_ERROR_MESSAGE_KEY= "ContentAssistant.error_computing_context"; //$NON-NLS-1$

	private BoldStylerProvider fBoldStylerProvider;

	private IInformationControlCreator fInformationControlCreator;
	private int fAutoActivationDelay= DEFAULT_AUTO_ACTIVATION_DELAY;
	private boolean fIsAutoActivated= false;
	private boolean fIsAutoInserting= false;
	private int fProposalPopupOrientation= PROPOSAL_OVERLAY;
	private int fContextInfoPopupOrientation= CONTEXT_INFO_ABOVE;
	private Map<String, Set<IContentAssistProcessor>> fProcessors;

	/**
	 * The partitioning.
	 *
	 * @since 3.0
	 */
	private String fPartitioning;

	private Color fContextInfoPopupBackground;
	private Color fContextInfoPopupForeground;
	private Color fContextSelectorBackground;
	private Color fContextSelectorForeground;
	private Color fProposalSelectorBackground;
	private Color fProposalSelectorForeground;

	private ITextViewer fViewer;
	private String fLastErrorMessage;

	private Closer fCloser;
	LayoutManager fLayoutManager;

	AutoAssistListener fAutoAssistListener;
	private InternalListener fInternalListener;
	private CompletionProposalPopup fProposalPopup;
	private ContextInformationPopup fContextInfoPopup;

	/**
	 * Flag which tells whether a verify key listener is hooked.
	 *
	 * @since 3.0
	 */
	private boolean fVerifyKeyListenerHooked= false;
	private IContentAssistListener[] fListeners= new IContentAssistListener[4];
	/**
	 * The content assist subject control.
	 *
	 * @since 3.0
	 */
	private IContentAssistSubjectControl fContentAssistSubjectControl;
	/**
	 * The content assist subject control's shell.
	 *
	 * @since 3.2
	 */
	private Shell fContentAssistSubjectControlShell;
	/**
	 * The content assist subject control's shell traverse listener.
	 *
	 * @since 3.2
	 */
	private TraverseListener fCASCSTraverseListener;
	/**
	 * The content assist subject control adapter.
	 *
	 * @since 3.0
	 */
	private ContentAssistSubjectControlAdapter fContentAssistSubjectControlAdapter;
	/**
	 * The dialog settings for the control's bounds.
	 *
	 * @since 3.0
	 */
	private IDialogSettings fDialogSettings;
	/**
	 * Prefix completion setting.
	 *
	 * @since 3.0
	 */
	private boolean fIsPrefixCompletionEnabled= false;
	/**
	 * The list of completion listeners.
	 *
	 * @since 3.2
	 */
	private ListenerList<ICompletionListener> fCompletionListeners= new ListenerList<>(ListenerList.IDENTITY);
	/**
	 * The message to display at the bottom of the proposal popup.
	 *
	 * @since 3.2
	 */
	private String fMessage= ""; //$NON-NLS-1$
	/**
	 * The cycling mode property.
	 *
	 * @since 3.2
	 */
	private boolean fIsRepetitionMode= false;
	/**
	 * The show empty property.
	 *
	 * @since 3.2
	 */
	private boolean fShowEmptyList= false;
	/**
	 * The message line property.
	 *
	 * @since 3.2
	 */
	private boolean fIsStatusLineVisible;
	/**
	 * The last system time when auto activation performed.
	 *
	 * @since 3.2
	 */
	private long fLastAutoActivation= Long.MIN_VALUE;
	/**
	 * The iteration key sequence to listen for, or <code>null</code>.
	 *
	 * @since 3.2
	 */
	private KeySequence fRepeatedInvocationKeySequence;

	/**
	 * Maps handler to command identifiers.
	 *
	 * @since 3.4
	 */
	private Map<String, IHandler> fHandlers;

	/**
	 * Tells whether colored labels support is enabled.
	 *
	 * @since 3.4
	 */
	private boolean fIsColoredLabelsSupportEnabled= false;

	/**
	 * The sorter to be used for sorting the proposals or <code>null</code> if no sorting is
	 * requested.
	 *
	 * @since 3.8
	 */
	private ICompletionProposalSorter fSorter;

	/**
	 * Tells whether this content assistant allows to run asynchronous
	 *
	 * @since 3.12
	 */
	private boolean fAsynchronous;

	private boolean fCompletionProposalTriggerCharsEnabled= true;

	/**
	 * Creates a new content assistant. The content assistant is not automatically activated,
	 * overlays the completion proposals with context information list if necessary, and shows the
	 * context information above the location at which it was activated. If auto activation will be
	 * enabled, without further configuration steps, this content assistant is activated after a 500
	 * milliseconds delay. It uses the default partitioning.
	 */
	public ContentAssistant() {
		this(false);
	}

	/**
	 * Creates a new content assistant. The content assistant is not automatically activated,
	 * overlays the completion proposals with context information list if necessary, and shows the
	 * context information above the location at which it was activated. If auto activation will be
	 * enabled, without further configuration steps, this content assistant is activated after a 500
	 * milliseconds delay. It uses the default partitioning.
	 *
	 * @param asynchronous <code>true</code> if this content assistant should present the proposals
	 *            asynchronously, <code>false</code> otherwise
	 * @since 3.12
	 */
	public ContentAssistant(boolean asynchronous) {
		fPartitioning= IDocumentExtension3.DEFAULT_PARTITIONING;
		fAsynchronous= asynchronous;
	}

	/**
	 * Sets the document partitioning this content assistant is using.
	 *
	 * @param partitioning the document partitioning for this content assistant
	 * @since 3.0
	 */
	public void setDocumentPartitioning(String partitioning) {
		Assert.isNotNull(partitioning);
		fPartitioning= partitioning;
	}

	@Override
	public String getDocumentPartitioning() {
		return fPartitioning;
	}

	/**
	 * Registers a given content assist processor for a particular content type. If there is already
	 * a processor registered for this type, the new processor is registered instead of the old one.
	 *
	 * @param processor the content assist processor to register, or <code>null</code> to remove
	 *        an existing one
	 * @param contentType the content type under which to register
	 */
	public void setContentAssistProcessor(IContentAssistProcessor processor, String contentType) {

		Assert.isNotNull(contentType);

		if (fProcessors == null)
			fProcessors= new HashMap<>();

		if (processor == null)
			fProcessors.remove(contentType);
		else
			fProcessors.put(contentType, Collections.singleton(processor));
	}

	/**
	 * Registers a given content assist processor for a particular content type. If there is already
	 * a processor registered for this type, it is kept and the new processor is appended to the list
	 * of processors for given content-type.
	 *
	 * @param processor The content-assist process to add
	 * @param contentType Document token content-type it applies to
	 * @since 3.12
	 */
	public void addContentAssistProcessor(IContentAssistProcessor processor, String contentType) {
		Assert.isNotNull(contentType);

		if (fProcessors == null)
			fProcessors= new HashMap<>();

		if (processor == null) {
			fProcessors.remove(contentType);
		} else {
			fProcessors.computeIfAbsent(contentType, key -> new LinkedHashSet<>()).add(processor);
		}
	}

	/**
	 * removes the given processor from all content types in this {@link ContentAssistant}
	 *
	 * @param processor The content-assist process to remove
	 * @since 3.17
	 */
	public void removeContentAssistProcessor(IContentAssistProcessor processor) {
		if (fProcessors == null || processor == null) {
			return;
		}
		for (Set<IContentAssistProcessor> set : fProcessors.values()) {
			set.remove(processor);
		}
	}

	/*
	 * @see IContentAssistant#getContentAssistProcessor
	 */
	@Override
	public IContentAssistProcessor getContentAssistProcessor(String contentType) {
		if (fProcessors == null)
			return null;

		Set<IContentAssistProcessor> res = fProcessors.get(contentType);
		if (res == null || res.isEmpty()) {
			return null;
		} else {
			return res.iterator().next(); // return first one although there might be multiple ones... TODO, consider an aggregator contentAssistProcessor to return here
		}
	}

	/**
	 * Returns the content assist processors to be used for the given content type.
	 *
	 * @param contentType the type of the content for which this content assistant is to be
	 *            requested
	 * @return the content assist processors or <code>null</code> if none exists for the specified
	 *         content type
	 * @since 3.12
	 */
	Set<IContentAssistProcessor> getContentAssistProcessors(String contentType) {
		if (fProcessors == null)
			return null;

		Set<IContentAssistProcessor> res = fProcessors.get(contentType);
		if (res == null || res.isEmpty()) {
			return null;
		}
		return res;
	}

	/**
	 * @param c the character to check
	 * @return whether the given char is an auto-activation trigger char
	 * @since 3.15
	 */
	TriggerType getAutoActivationTriggerType(char c) {
		if (fProcessors == null)
			return TriggerType.NONE;
		int offset= fContentAssistSubjectControlAdapter.getSelectedRange().x;
		Set<IContentAssistProcessor> processors= fContentAssistSubjectControlAdapter.getContentAssistProcessors(this, offset);
		if (processors == null) {
			return TriggerType.NONE;
		}
		for (IContentAssistProcessor processor : processors) {
			IContentAssistProcessorExtension extension= IContentAssistProcessorExtension.adapt(processor);
			if (extension.isCompletionProposalAutoActivation(c, fViewer, offset)) {
				return TriggerType.COMPLETION_PROPOSAL;
			}
			if (extension.isContextInformationAutoActivation(c, fViewer, offset)) {
				return TriggerType.CONTEXT_INFORMATION;
			}
		}
		return TriggerType.NONE;
	}

	/**
	 * Enables the content assistant's auto activation mode.
	 *
	 * @param enabled indicates whether auto activation is enabled or not
	 */
	public void enableAutoActivation(boolean enabled) {
		fIsAutoActivated= enabled;
		manageAutoActivation(fIsAutoActivated);
	}

	/**
	 * Enables the content assistant's auto insertion mode. If enabled, the content assistant
	 * inserts a proposal automatically if it is the only proposal. In the case of ambiguities, the
	 * user must make the choice.
	 *
	 * @param enabled indicates whether auto insertion is enabled or not
	 * @since 2.0
	 */
	public void enableAutoInsert(boolean enabled) {
		fIsAutoInserting= enabled;
	}

	/**
	 * Returns whether this content assistant is in the auto insertion mode or not.
	 *
	 * @return <code>true</code> if in auto insertion mode
	 * @since 2.0
	 */
	boolean isAutoInserting() {
		return fIsAutoInserting;
	}

	/**
	 * Installs and uninstall the listeners needed for auto activation.
	 *
	 * @param start <code>true</code> if listeners must be installed, <code>false</code> if they
	 *        must be removed
	 * @since 2.0
	 */
	private void manageAutoActivation(boolean start) {
		if (start) {

			if ((fContentAssistSubjectControlAdapter != null) && fAutoAssistListener == null) {
				fAutoAssistListener= createAutoAssistListener();
				// For details see https://bugs.eclipse.org/bugs/show_bug.cgi?id=49212
				if (fContentAssistSubjectControlAdapter.supportsVerifyKeyListener())
					fContentAssistSubjectControlAdapter.appendVerifyKeyListener(fAutoAssistListener);
				else
					fContentAssistSubjectControlAdapter.addKeyListener(fAutoAssistListener);
			}

		} else if (fAutoAssistListener != null) {
			// For details see https://bugs.eclipse.org/bugs/show_bug.cgi?id=49212
			if (fContentAssistSubjectControlAdapter.supportsVerifyKeyListener())
				fContentAssistSubjectControlAdapter.removeVerifyKeyListener(fAutoAssistListener);
			else
				fContentAssistSubjectControlAdapter.removeKeyListener(fAutoAssistListener);
			fAutoAssistListener= null;
		}
	}

	/**
	 * This method allows subclasses to provide their own {@link AutoAssistListener}.
	 *
	 * @return a new auto assist listener
	 * @since 3.4
	 */
	protected AutoAssistListener createAutoAssistListener() {
		return new AutoAssistListener();
	}

	/**
	 * Sets the delay after which the content assistant is automatically invoked if the cursor is
	 * behind an auto activation character.
	 *
	 * @param delay the auto activation delay (as of 3.6 a negative argument will be set to 0)
	 */
	public void setAutoActivationDelay(int delay) {
		fAutoActivationDelay= Math.max(0, delay);
	}

	/**
	 * Gets the delay after which the content assistant is automatically invoked if the cursor is
	 * behind an auto activation character.
	 *
	 * @return the auto activation delay (will not be negative)
	 * @since 3.4
	 */
	public int getAutoActivationDelay() {
		return fAutoActivationDelay;
	}

	/**
	 * Sets the proposal pop-ups' orientation. The following values may be used:
	 * <ul>
	 *   <li>PROPOSAL_OVERLAY<p>
	 *     proposal popup windows should overlay each other
	 *   </li>
	 *   <li>PROPOSAL_REMOVE<p>
	 *     any currently shown proposal popup should be closed
	 *   </li>
	 *   <li>PROPOSAL_STACKED<p>
	 *     proposal popup windows should be vertical stacked, with no overlap,
	 *     beneath the line containing the current cursor location
	 *   </li>
	 * </ul>
	 *
	 * @param orientation the popup's orientation
	 */
	public void setProposalPopupOrientation(int orientation) {
		fProposalPopupOrientation= orientation;
	}

	/**
	 * Sets the context information popup's orientation.
	 * The following values may be used:
	 * <ul>
	 *   <li>CONTEXT_ABOVE<p>
	 *     context information popup should always appear above the line containing
	 *     the current cursor location
	 *   </li>
	 *   <li>CONTEXT_BELOW<p>
	 *     context information popup should always appear below the line containing
	 *     the current cursor location
	 *   </li>
	 * </ul>
	 *
	 * @param orientation the popup's orientation
	 */
	public void setContextInformationPopupOrientation(int orientation) {
		fContextInfoPopupOrientation= orientation;
	}

	/**
	 * Sets the context information popup's background color.
	 *
	 * @param background the background color
	 */
	public void setContextInformationPopupBackground(Color background) {
		fContextInfoPopupBackground= background;
	}

	/**
	 * Returns the background of the context information popup.
	 *
	 * @return the background of the context information popup
	 * @since 2.0
	 */
	Color getContextInformationPopupBackground() {
		return fContextInfoPopupBackground;
	}

	/**
	 * Sets the context information popup's foreground color.
	 *
	 * @param foreground the foreground color
	 * @since 2.0
	 */
	public void setContextInformationPopupForeground(Color foreground) {
		fContextInfoPopupForeground= foreground;
	}

	/**
	 * Returns the foreground of the context information popup.
	 *
	 *
	 * @return the foreground of the context information popup
	 * @since 2.0
	 */
	Color getContextInformationPopupForeground() {
		return fContextInfoPopupForeground;
	}

	/**
	 * Sets the proposal selector's background color.
	 * <p>
	 * <strong>Note:</strong> As of 3.4, you should only call this
	 * method if you want to override the {@link JFacePreferences#CONTENT_ASSIST_BACKGROUND_COLOR}.
	 * </p>
	 *
	 * @param background the background color
	 * @since 2.0
	 */
	public void setProposalSelectorBackground(Color background) {
		fProposalSelectorBackground= background;
	}

	/**
	 * Returns the custom background color of the proposal selector.
	 *
	 * @return the background of the proposal selector or <code>null</code> if not set
	 * @since 2.0
	 */
	Color getProposalSelectorBackground() {
		return fProposalSelectorBackground;
	}

	/**
	 * Sets the proposal's foreground color.
	 * <p>
	 * <strong>Note:</strong> As of 3.4, you should only call this
	 * method if you want to override the {@link JFacePreferences#CONTENT_ASSIST_FOREGROUND_COLOR}.
	 * </p>
	 *
	 * @param foreground the foreground color
	 * @since 2.0
	 */
	public void setProposalSelectorForeground(Color foreground) {
		fProposalSelectorForeground= foreground;
	}

	/**
	 * Returns the custom foreground color of the proposal selector.
	 *
	 * @return the foreground of the proposal selector or <code>null</code> if not set
	 * @since 2.0
	 */
	Color getProposalSelectorForeground() {
		return fProposalSelectorForeground;
	}

	/**
	 * Sets the {@link BoldStylerProvider} used to emphasize matches in a proposal's styled display
	 * string.
	 *
	 * @param boldStylerProvider the bold styler provider
	 *
	 * @see ICompletionProposalExtension7#getStyledDisplayString(IDocument, int, BoldStylerProvider)
	 * @since 3.11
	 */
	void setBoldStylerProvider(BoldStylerProvider boldStylerProvider) {
		fBoldStylerProvider= boldStylerProvider;
	}

	/**
	 * Returns the {@link BoldStylerProvider} used to emphasize matches in a proposal's styled
	 * display string.
	 *
	 * @see ICompletionProposalExtension7#getStyledDisplayString(IDocument, int, BoldStylerProvider)
	 *
	 * @return the {@link BoldStylerProvider}, or <code>null</code> if not set
	 * @since 3.11
	 */
	BoldStylerProvider getBoldStylerProvider() {
		return fBoldStylerProvider;
	}

	/**
	 * Sets the context selector's background color.
	 *
	 * @param background the background color
	 * @since 2.0
	 */
	public void setContextSelectorBackground(Color background) {
		fContextSelectorBackground= background;
	}

	/**
	 * Returns the background of the context selector.
	 *
	 * @return the background of the context selector
	 * @since 2.0
	 */
	Color getContextSelectorBackground() {
		return fContextSelectorBackground;
	}

	/**
	 * Sets the context selector's foreground color.
	 *
	 * @param foreground the foreground color
	 * @since 2.0
	 */
	public void setContextSelectorForeground(Color foreground) {
		fContextSelectorForeground= foreground;
	}

	/**
	 * Returns the foreground of the context selector.
	 *
	 * @return the foreground of the context selector
	 * @since 2.0
	 */
	Color getContextSelectorForeground() {
		return fContextSelectorForeground;
	}

	/**
	 * Sets the information control creator for the additional information control.
	 *
	 * @param creator the information control creator for the additional information control
	 * @since 2.0
	 */
	public void setInformationControlCreator(IInformationControlCreator creator) {
		fInformationControlCreator= creator;
	}

	/*
	 * @see IControlContentAssistant#install(IContentAssistSubjectControl)
	 * @since 3.0
	 */
	protected void install(IContentAssistSubjectControl contentAssistSubjectControl) {
		fContentAssistSubjectControl= contentAssistSubjectControl;
		fContentAssistSubjectControlAdapter= new ContentAssistSubjectControlAdapter(fContentAssistSubjectControl);
		install();
	}

	/*
	 * @see IContentAssist#install
	 * @since 3.0
	 */
	@Override
	public void install(ITextViewer textViewer) {
		fViewer= textViewer;
		fContentAssistSubjectControlAdapter= new ContentAssistSubjectControlAdapter(fViewer);
		install();
	}

	protected void install() {

		fLayoutManager= new LayoutManager();
		fInternalListener= new InternalListener();

		AdditionalInfoController controller= null;
		if (fInformationControlCreator != null)
			controller= new AdditionalInfoController(fInformationControlCreator, OpenStrategy.getPostSelectionDelay());

		fContextInfoPopup= fContentAssistSubjectControlAdapter.createContextInfoPopup(this);
		fProposalPopup= fContentAssistSubjectControlAdapter.createCompletionProposalPopup(this, controller, fAsynchronous);
		fProposalPopup.setSorter(fSorter);

		registerHandler(SELECT_NEXT_PROPOSAL_COMMAND_ID, fProposalPopup.createProposalSelectionHandler(CompletionProposalPopup.ProposalSelectionHandler.SELECT_NEXT));
		registerHandler(SELECT_PREVIOUS_PROPOSAL_COMMAND_ID, fProposalPopup.createProposalSelectionHandler(CompletionProposalPopup.ProposalSelectionHandler.SELECT_PREVIOUS));

		if (isValid(fContentAssistSubjectControlAdapter.getControl())) {
			fContentAssistSubjectControlShell= fContentAssistSubjectControlAdapter.getControl().getShell();
			fCASCSTraverseListener= e -> {
				if (e.detail == SWT.TRAVERSE_ESCAPE && isProposalPopupActive())
					e.doit= false;
			};
			fContentAssistSubjectControlShell.addTraverseListener(fCASCSTraverseListener);
		}

		manageAutoActivation(fIsAutoActivated);
	}

	/*
	 * @see IContentAssist#uninstall
	 */
	@Override
	public void uninstall() {
		hide();

		if (fBoldStylerProvider != null) {
			fBoldStylerProvider.dispose();
			fBoldStylerProvider= null;
		}

		manageAutoActivation(false);

		if (fHandlers != null) {
			fHandlers.clear();
			fHandlers= null;
		}

		if (fCloser != null) {
			fCloser.uninstall();
			fCloser= null;
		}

		if (isValid(fContentAssistSubjectControlShell))
			fContentAssistSubjectControlShell.removeTraverseListener(fCASCSTraverseListener);
		fCASCSTraverseListener= null;
		fContentAssistSubjectControlShell= null;

		fViewer= null;
		fContentAssistSubjectControl= null;
		fContentAssistSubjectControlAdapter= null;
	}

	/**
	 * Adds the given shell of the specified type to the layout. Valid types are defined by
	 * <code>LayoutManager</code>.
	 *
	 * @param popup a content assist popup
	 * @param shell the shell of the content-assist popup
	 * @param type the type of popup
	 * @param visibleOffset the offset at which to layout the popup relative to the offset of the
	 *        viewer's visible region
	 * @since 2.0
	 */
	void addToLayout(Object popup, Shell shell, int type, int visibleOffset) {
		fLayoutManager.add(popup, shell, type, visibleOffset);
	}

	/**
	 * Layouts the registered popup of the given type relative to the given offset. The offset is
	 * relative to the offset of the viewer's visible region. Valid types are defined by
	 * <code>LayoutManager</code>.
	 *
	 * @param type the type of popup to layout
	 * @param visibleOffset the offset at which to layout relative to the offset of the viewer's
	 *        visible region
	 * @since 2.0
	 */
	void layout(int type, int visibleOffset) {
		fLayoutManager.layout(type, visibleOffset);
	}

	/**
	 * Returns the layout manager.
	 *
	 * @return the layout manager
	 * @since 3.3
	 */
	LayoutManager getLayoutManager() {
		return fLayoutManager;
	}

	/**
	 * Notifies the controller that a popup has lost focus.
	 *
	 * @param e the focus event
	 */
	void popupFocusLost(FocusEvent e) {
		fCloser.focusLost(e);
	}

	/**
	 * Returns the offset of the selection relative to the offset of the visible region.
	 *
	 * @return the offset of the selection relative to the offset of the visible region
	 * @since 2.0
	 */
	int getSelectionOffset() {
		return fContentAssistSubjectControlAdapter.getWidgetSelectionRange().x;
	}

	/**
	 * Returns whether the widget token could be acquired. The following are valid listener types:
	 * <ul>
	 *   <li>AUTO_ASSIST</li>
	 *   <li>CONTEXT_SELECTOR</li>
	 *   <li>PROPOSAL_SELECTOR</li>
	 *   <li>CONTEXT_INFO_POPUP</li>
	 * </ul>
	 *
	 * @param type the listener type for which to acquire
	 * @return <code>true</code> if the widget token could be acquired
	 * @since 2.0
	 */
	private boolean acquireWidgetToken(int type) {
		switch (type) {
			case CONTEXT_SELECTOR:
			case PROPOSAL_SELECTOR:
				if (fContentAssistSubjectControl instanceof IWidgetTokenOwnerExtension) {
					IWidgetTokenOwnerExtension extension= (IWidgetTokenOwnerExtension) fContentAssistSubjectControl;
					return extension.requestWidgetToken(this, WIDGET_PRIORITY);
				} else if (fContentAssistSubjectControl instanceof IWidgetTokenOwner) {
					IWidgetTokenOwner owner= (IWidgetTokenOwner) fContentAssistSubjectControl;
					return owner.requestWidgetToken(this);
				} else if (fViewer instanceof IWidgetTokenOwnerExtension) {
					IWidgetTokenOwnerExtension extension= (IWidgetTokenOwnerExtension) fViewer;
					return extension.requestWidgetToken(this, WIDGET_PRIORITY);
				} else if (fViewer instanceof IWidgetTokenOwner) {
					IWidgetTokenOwner owner= (IWidgetTokenOwner) fViewer;
					return owner.requestWidgetToken(this);
				}
		}
		return true;
	}

	/**
	 * Registers a content assist listener. The following are valid listener types:
	 * <ul>
	 *   <li>AUTO_ASSIST</li>
	 *   <li>CONTEXT_SELECTOR</li>
	 *   <li>PROPOSAL_SELECTOR</li>
	 *   <li>CONTEXT_INFO_POPUP</li>
	 * </ul>
	 * Returns whether the listener could be added successfully. A listener can not be added if the
	 * widget token could not be acquired.
	 *
	 * @param listener the listener to register
	 * @param type the type of listener
	 * @return <code>true</code> if the listener could be added
	 */
	boolean addContentAssistListener(IContentAssistListener listener, int type) {

		if (acquireWidgetToken(type)) {

			fListeners[type]= listener;

			if (fCloser == null && getNumberOfListeners() == 1) {
				fCloser= new Closer();
				fCloser.install();
				fContentAssistSubjectControlAdapter.setEventConsumer(fInternalListener);
				installKeyListener();
			} else
				promoteKeyListener();
			return true;
		}

		return false;
	}

	/**
	 * Re-promotes the key listener to the first position, using prependVerifyKeyListener. This
	 * ensures no other instance is filtering away the keystrokes underneath, if we've been up for a
	 * while (e.g. when the context info is showing.
	 *
	 * @since 3.0
	 */
	private void promoteKeyListener() {
		uninstallVerifyKeyListener();
		installKeyListener();
	}

	/**
	 * Installs a key listener on the text viewer's widget.
	 */
	private void installKeyListener() {
		if (!fVerifyKeyListenerHooked) {
			if (isValid(fContentAssistSubjectControlAdapter.getControl())) {
				fVerifyKeyListenerHooked= fContentAssistSubjectControlAdapter.prependVerifyKeyListener(fInternalListener);
			}
		}
	}

	/**
	 * Releases the previously acquired widget token if the token is no longer necessary. The
	 * following are valid listener types:
	 * <ul>
	 *   <li>AUTO_ASSIST</li>
	 *   <li>CONTEXT_SELECTOR</li>
	 *   <li>PROPOSAL_SELECTOR</li>
	 *   <li>CONTEXT_INFO_POPUP</li>
	 * </ul>
	 *
	 * @param type the listener type
	 * @since 2.0
	 */
	private void releaseWidgetToken(int type) {
		if (fListeners[CONTEXT_SELECTOR] == null && fListeners[PROPOSAL_SELECTOR] == null) {
			IWidgetTokenOwner owner= null;
			if (fContentAssistSubjectControl instanceof IWidgetTokenOwner)
				owner= (IWidgetTokenOwner) fContentAssistSubjectControl;
			else if (fViewer instanceof IWidgetTokenOwner)
				owner= (IWidgetTokenOwner) fViewer;
			if (owner != null)
				owner.releaseWidgetToken(this);
		}
	}

	/**
	 * Unregisters a content assist listener.
	 *
	 * @param listener the listener to unregister
	 * @param type the type of listener
	 * @see #addContentAssistListener(IContentAssistListener, int)
	 */
	void removeContentAssistListener(IContentAssistListener listener, int type) {
		fListeners[type]= null;

		if (getNumberOfListeners() == 0) {

			if (fCloser != null) {
				fCloser.uninstall();
				fCloser= null;
			}

			uninstallVerifyKeyListener();
			fContentAssistSubjectControlAdapter.setEventConsumer(null);
		}

		releaseWidgetToken(type);
	}

	/**
	 * Uninstall the key listener from the text viewer's widget.
	 *
	 * @since 3.0
	 */
	private void uninstallVerifyKeyListener() {
		if (fVerifyKeyListenerHooked) {
			if (isValid(fContentAssistSubjectControlAdapter.getControl()))
				fContentAssistSubjectControlAdapter.removeVerifyKeyListener(fInternalListener);
			fVerifyKeyListenerHooked= false;
		}
	}

	/**
	 * Returns the number of listeners.
	 *
	 * @return the number of listeners
	 * @since 2.0
	 */
	private int getNumberOfListeners() {
		int count= 0;
		for (int i= 0; i <= CONTEXT_INFO_POPUP; i++) {
			if (fListeners[i] != null)
				++count;
		}
		return count;
	}

	/*
	 * @see IContentAssist#showPossibleCompletions
	 */
	@Override
	public String showPossibleCompletions() {
		if (!prepareToShowCompletions(false))
			return null;
		if (fIsPrefixCompletionEnabled)
			return fProposalPopup.incrementalComplete();
		return fProposalPopup.showProposals(false);
	}

	@Override
	public String completePrefix() {
		if (!prepareToShowCompletions(false))
			return null;
		return fProposalPopup.incrementalComplete();
	}

	/**
	 * Prepares to show content assist proposals. It returns false if auto activation has kicked in
	 * recently.
	 *
	 * @param isAutoActivated  whether completion was triggered by auto activation
	 * @return <code>true</code> if the caller should continue and show the proposals,
	 *         <code>false</code> otherwise.
	 * @since 3.2
	 */
	private boolean prepareToShowCompletions(boolean isAutoActivated) {
		if (!isAutoActivated) {
			int gracePeriod= Math.max(fAutoActivationDelay, 200);
			if (System.currentTimeMillis() < fLastAutoActivation + gracePeriod) {
				return false;
			}
		}

		promoteKeyListener();
		fireSessionBeginEvent(isAutoActivated);
		return true;
	}

	/**
	 * Callback to signal this content assistant that the presentation of the possible completions
	 * has been stopped.
	 *
	 * @since 2.1
	 */
	protected void possibleCompletionsClosed() {
		fLastAutoActivation= Long.MIN_VALUE;
		storeCompletionProposalPopupSize();
	}

	/*
	 * @see IContentAssist#showContextInformation
	 */
	@Override
	public String showContextInformation() {
		promoteKeyListener();
		if (fContextInfoPopup != null)
			return fContextInfoPopup.showContextProposals(false);
		return null;
	}

	/**
	 * Callback to signal this content assistant that the presentation of the context information
	 * has been stopped.
	 *
	 * @since 2.1
	 */
	protected void contextInformationClosed() {
	}

	/**
	 * Requests that the specified context information to be shown.
	 *
	 * @param contextInformation the context information to be shown
	 * @param offset the offset to which the context information refers to
	 * @since 2.0
	 */
	void showContextInformation(IContextInformation contextInformation, int offset) {
		if (fContextInfoPopup != null)
			fContextInfoPopup.showContextInformation(contextInformation, offset);
	}

	/**
	 * Returns the current content assist error message.
	 *
	 * @return an error message or <code>null</code> if no error has occurred
	 */
	String getErrorMessage() {
		return fLastErrorMessage;
	}

	/**
	 * Returns the content assist processor for the content type of the specified document position.
	 *
	 * @param viewer the text viewer
	 * @param offset a offset within the document
	 * @return the content-assist processors or <code>null</code> if none exists
	 * @since 3.13
	 */
	Set<IContentAssistProcessor> getProcessors(ITextViewer viewer, int offset) {
		try {

			IDocument document= viewer.getDocument();
			String type= TextUtilities.getContentType(document, getDocumentPartitioning(), offset, true);

			return getContentAssistProcessors(type);

		} catch (BadLocationException x) {
		}

		return null;
	}

	/**
	 * Returns the content assist processors for the content type of the specified document position.
	 *
	 * @param contentAssistSubjectControl the content assist subject control
	 * @param offset a offset within the document
	 * @return the content-assist processors or <code>null</code> if none exists
	 * @since 3.13
	 */
	Set<IContentAssistProcessor> getProcessors(IContentAssistSubjectControl contentAssistSubjectControl, int offset) {
		try {

			IDocument document= contentAssistSubjectControl.getDocument();
			String type;
			if (document != null)
				type= TextUtilities.getContentType(document, getDocumentPartitioning(), offset, true);
			else
				type= IDocument.DEFAULT_CONTENT_TYPE;

			return getContentAssistProcessors(type);

		} catch (BadLocationException x) {
		}

		return null;
	}

	/**
	 * Returns an array of completion proposals computed based on the specified document position.
	 * The position is used to determine the appropriate content assist processor to invoke.
	 *
	 * @param contentAssistSubjectControl the content assist subject control
	 * @param offset a document offset
	 * @return an array of completion proposals or <code>null</code> if no proposals are possible
	 * @see IContentAssistProcessor#computeCompletionProposals(ITextViewer, int)
	 * @since 3.0
	 */
	ICompletionProposal[] computeCompletionProposals(
			final IContentAssistSubjectControl contentAssistSubjectControl, final int offset) {
		fLastErrorMessage= null;

		final List<ICompletionProposal> result= new ArrayList<>();
		final Set<IContentAssistProcessor> processors= getProcessors(contentAssistSubjectControl, offset);
		if (processors != null) {
			processors.forEach(p -> {
				if (p instanceof ISubjectControlContentAssistProcessor) {
					// Ensure that the assist session ends cleanly even if the processor throws an exception.
					SafeRunner.run(new ExceptionLoggingSafeRunnable(COMPLETION_ERROR_MESSAGE_KEY) {
						@Override
						public void run() throws Exception {
							ICompletionProposal[] proposals= ((ISubjectControlContentAssistProcessor) p)
									.computeCompletionProposals(contentAssistSubjectControl, offset);
							if (proposals != null) {
								result.addAll(Arrays.asList(proposals));
							}
							fLastErrorMessage= p.getErrorMessage();
						}
					});
				}
			});
		}

		return result.isEmpty() ? null : result.toArray(new ICompletionProposal[result.size()]);
	}

	/**
	 * Returns an array of completion proposals computed based on the specified document position.
	 * The position is used to determine the appropriate content assist processor to invoke.
	 *
	 * @param viewer the viewer for which to compute the proposals
	 * @param offset a document offset
	 * @return an array of completion proposals or <code>null</code> if no proposals are possible
	 * @see IContentAssistProcessor#computeCompletionProposals(ITextViewer, int)
	 */
	ICompletionProposal[] computeCompletionProposals(final ITextViewer viewer, final int offset) {
		fLastErrorMessage= null;

		final Set<IContentAssistProcessor> processors= getProcessors(viewer, offset);
		final List<ICompletionProposal> res = new ArrayList<>();
		if (processors != null && !processors.isEmpty()) {
			// Ensure that the assist session ends cleanly even if the processor throws an exception.
			SafeRunner.run(new ExceptionLoggingSafeRunnable(COMPLETION_ERROR_MESSAGE_KEY) {
				@Override
				public void run() throws Exception {
					processors.forEach(p -> {
						ICompletionProposal[] proposals= p.computeCompletionProposals(viewer, offset);
						if (proposals != null) {
							res.addAll(Arrays.asList(proposals));
						}
						fLastErrorMessage= p.getErrorMessage();
					});
				}
			});
		}

		return res.isEmpty() ? null : res.toArray(new ICompletionProposal[res.size()]);
	}

	/**
	 * Returns an array of context information objects computed based on the specified document
	 * position. The position is used to determine the appropriate content assist processor to
	 * invoke.
	 *
	 * @param viewer the viewer for which to compute the context information
	 * @param offset a document offset
	 * @return an array of context information objects
	 * @see IContentAssistProcessor#computeContextInformation(ITextViewer, int)
	 */
	IContextInformation[] computeContextInformation(final ITextViewer viewer, final int offset) {
		fLastErrorMessage= null;

		final List<IContextInformation> result= new ArrayList<>();
		final Set<IContentAssistProcessor> processors= getProcessors(viewer, offset);
		if (processors != null && !processors.isEmpty()) {
			// Ensure that the assist session ends cleanly even if the processor throws an exception.
			SafeRunner.run(new ExceptionLoggingSafeRunnable(CONTEXT_ERROR_MESSAGE_KEY) {
				@Override
				public void run() throws Exception {
					processors.forEach(p -> {
						IContextInformation[] contextInformation= p.computeContextInformation(viewer, offset);
						if (contextInformation != null) {
							result.addAll(Arrays.asList(contextInformation));
						}
						fLastErrorMessage= p.getErrorMessage();
					});
				}
			});
		}

		return result.isEmpty() ? null : result.toArray(new IContextInformation[result.size()]);
	}

	/**
	 * Returns an array of context information objects computed based on the specified document
	 * position. The position is used to determine the appropriate content assist processor to
	 * invoke.
	 *
	 * @param contentAssistSubjectControl the content assist subject control
	 * @param offset a document offset
	 * @return an array of context information objects
	 * @see IContentAssistProcessor#computeContextInformation(ITextViewer, int)
	 * @since 3.0
	 */
	IContextInformation[] computeContextInformation(
			final IContentAssistSubjectControl contentAssistSubjectControl, final int offset) {
		fLastErrorMessage= null;

		final List<IContextInformation> result= new ArrayList<>();
		final Set<IContentAssistProcessor> processors = getProcessors(contentAssistSubjectControl, offset);
		if (processors != null) {
			processors.forEach(p -> {
				if (p instanceof ISubjectControlContentAssistProcessor) {
					// Ensure that the assist session ends cleanly even if the processor throws an exception.
					SafeRunner.run(new ExceptionLoggingSafeRunnable(CONTEXT_ERROR_MESSAGE_KEY) {
						@Override
						public void run() throws Exception {
							IContextInformation[] contextInformation= ((ISubjectControlContentAssistProcessor) p)
									.computeContextInformation(contentAssistSubjectControl, offset);
							if (contextInformation != null) {
								result.addAll(Arrays.asList(contextInformation));
							}
							fLastErrorMessage= p.getErrorMessage();
						}
					});
				}
			});
		}

		return result.isEmpty() ? null : result.toArray(new IContextInformation[result.size()]);
	}

	/**
	 * Returns the context information validator that should be used to determine when the currently
	 * displayed context information should be dismissed. The position is used to determine the
	 * appropriate content assist processor to invoke.
	 *
	 * @param viewer the text viewer
	 * @param offset a document offset
	 * @return an validator
	 * @see IContentAssistProcessor#getContextInformationValidator()
	 * @since 3.0
	 */
	IContextInformationValidator getContextInformationValidator(ITextViewer viewer, int offset) {
		Set<IContentAssistProcessor> processors= getProcessors(viewer, offset);
		if (processors == null || processors.isEmpty()) {
			return null;
		}
		IContextInformationValidator[] validators= processors.stream()
				.map(IContentAssistProcessor::getContextInformationValidator)
				.filter(Objects::nonNull)
				.toArray(IContextInformationValidator[]::new);
		if (validators.length == 0) {
			return null;
		} else if (validators.length == 1) {
			return validators[0];
		}
		return new CompositeContextInformationValidator(validators);
	}

	/**
	 * Returns the context information validator that should be used to determine when the currently
	 * displayed context information should be dismissed. The position is used to determine the
	 * appropriate content assist processor to invoke.
	 *
	 * @param contentAssistSubjectControl the content assist subject control
	 * @param offset a document offset
	 * @return an validator
	 * @see IContentAssistProcessor#getContextInformationValidator()
	 * @since 3.0
	 */
	IContextInformationValidator getContextInformationValidator(IContentAssistSubjectControl contentAssistSubjectControl, int offset) {
		Set<IContentAssistProcessor> processors= getProcessors(contentAssistSubjectControl, offset);
		if (processors == null || processors.isEmpty()) {
			return null;
		}
		IContextInformationValidator[] validators= processors.stream()
				.map(IContentAssistProcessor::getContextInformationValidator)
				.filter(Objects::nonNull)
				.toArray(IContextInformationValidator[]::new);
		if (validators.length == 0) {
			return null;
		} else if (validators.length == 1) {
			return validators[0];
		}
		return new CompositeContextInformationValidator(validators);
	}

	/**
	 * Returns the context information presenter that should be used to display context information.
	 * The position is used to determine the appropriate content assist processor to invoke.
	 *
	 * @param viewer the text viewer
	 * @param offset a document offset
	 * @return a presenter
	 * @since 2.0
	 */
	IContextInformationPresenter getContextInformationPresenter(ITextViewer viewer, int offset) {
		IContextInformationValidator validator= getContextInformationValidator(viewer, offset);
		if (validator instanceof IContextInformationPresenter)
			return (IContextInformationPresenter) validator;
		return null;
	}

	/**
	 * Returns the context information presenter that should be used to display context information.
	 * The position is used to determine the appropriate content assist processor to invoke.
	 *
	 * @param contentAssistSubjectControl the content assist subject control
	 * @param offset a document offset
	 * @return a presenter
	 * @since 3.0
	 */
	IContextInformationPresenter getContextInformationPresenter(IContentAssistSubjectControl contentAssistSubjectControl, int offset) {
		IContextInformationValidator validator= getContextInformationValidator(contentAssistSubjectControl, offset);
		if (validator instanceof IContextInformationPresenter)
			return (IContextInformationPresenter) validator;
		return null;
	}

	@Override
	public boolean requestWidgetToken(IWidgetTokenOwner owner) {
		return false;
	}

	@Override
	public boolean requestWidgetToken(IWidgetTokenOwner owner, int priority) {
		if (priority > WIDGET_PRIORITY) {
			hide();
			return true;
		}
		return false;
	}

	@Override
	public boolean setFocus(IWidgetTokenOwner owner) {
		if (fProposalPopup != null) {
			fProposalPopup.setFocus();
			return fProposalPopup.hasFocus();
		}
		return false;
	}

	/**
	 * Hides any open pop-ups.
	 *
	 * @since 3.0
	 */
	protected void hide() {
		if (fProposalPopup != null)
			fProposalPopup.hide();

		if (fContextInfoPopup != null)
			fContextInfoPopup.hide();
	}

	// ------ control's size handling dialog settings ------

	/**
	 * Tells this information control manager to open the information control with the values
	 * contained in the given dialog settings and to store the control's last valid size in the
	 * given dialog settings.
	 * <p>
	 * Note: This API is only valid if the information control implements
	 * {@link org.eclipse.jface.text.IInformationControlExtension3}. Not following this restriction
	 * will later result in an {@link UnsupportedOperationException}.
	 * </p>
	 * <p>
	 * The constants used to store the values are:
	 * </p>
	 * <ul>
	 * <li>{@link ContentAssistant#STORE_SIZE_X}</li>
	 * <li>{@link ContentAssistant#STORE_SIZE_Y}</li>
	 * <li>{@link ContentAssistant#STORE_CONTEXT_SELECTOR_POPUP_SIZE_X}</li>
	 * <li>{@link ContentAssistant#STORE_CONTEXT_SELECTOR_POPUP_SIZE_Y}</li>
	 * </ul>
	 *
	 * @param dialogSettings the dialog settings
	 * @since 3.0
	 */
	public void setRestoreCompletionProposalSize(IDialogSettings dialogSettings) {
		Assert.isTrue(dialogSettings != null);
		fDialogSettings= dialogSettings;
	}

	/**
	 * Stores the content assist's proposal pop-up size.
	 */
	protected void storeCompletionProposalPopupSize() {
		if (fDialogSettings == null || fProposalPopup == null)
			return;

		Point size= fProposalPopup.getSize();
		if (size == null)
			return;

		fDialogSettings.put(STORE_SIZE_X, size.x);
		fDialogSettings.put(STORE_SIZE_Y, size.y);
	}

	/**
	 * Stores the content assist's context selector pop-up size.
	 *
	 * @since 3.9
	 */
	protected void storeContextSelectorPopupSize() {
		if (fDialogSettings == null || fContextInfoPopup == null)
			return;

		Point size= fContextInfoPopup.getContextSelectorPopupSize();
		if (size == null)
			return;

		fDialogSettings.put(STORE_CONTEXT_SELECTOR_POPUP_SIZE_X, size.x);
		fDialogSettings.put(STORE_CONTEXT_SELECTOR_POPUP_SIZE_Y, size.y);
	}

	/**
	 * Restores the content assist's proposal pop-up size.
	 *
	 * @return the stored size or <code>null</code> if none
	 * @since 3.0
	 */
	protected Point restoreCompletionProposalPopupSize() {
		if (fDialogSettings == null)
			return null;

		Point size= new Point(-1, -1);

		try {
			size.x= fDialogSettings.getInt(STORE_SIZE_X);
			size.y= fDialogSettings.getInt(STORE_SIZE_Y);
		} catch (NumberFormatException ex) {
			return null;
		}

		// sanity check
		if (size.x == -1 && size.y == -1)
			return null;

		Rectangle maxBounds= null;
		if (fContentAssistSubjectControl != null && isValid(fContentAssistSubjectControl.getControl()))
			maxBounds= fContentAssistSubjectControl.getControl().getDisplay().getBounds();
		else {
			// fallback
			Display display= Display.getCurrent();
			if (display == null)
				display= Display.getDefault();
			if (display != null && !display.isDisposed())
				maxBounds= display.getBounds();
		}

		if (size.x > -1 && size.y > -1) {
			if (maxBounds != null) {
				size.x= Math.min(size.x, maxBounds.width);
				size.y= Math.min(size.y, maxBounds.height);
			}

			// Enforce an absolute minimal size
			size.x= Math.max(size.x, 50);
			size.y= Math.max(size.y, 50);
		}

		return size;
	}

	/**
	 * Restores the content assist's context selector pop-up size.
	 *
	 * @return the stored size or <code>null</code> if none
	 * @since 3.9
	 */
	protected Point restoreContextSelectorPopupSize() {
		if (fDialogSettings == null)
			return null;

		Point size= new Point(-1, -1);

		try {
			size.x= fDialogSettings.getInt(STORE_CONTEXT_SELECTOR_POPUP_SIZE_X);
			size.y= fDialogSettings.getInt(STORE_CONTEXT_SELECTOR_POPUP_SIZE_Y);
		} catch (NumberFormatException ex) {
			return null;
		}

		// sanity check
		if (size.x == -1 && size.y == -1)
			return null;

		Rectangle maxBounds= null;
		Display display= Display.getCurrent();
		if (display == null)
			display= Display.getDefault();
		if (display != null && !display.isDisposed())
			maxBounds= display.getBounds();

		if (size.x > -1 && size.y > -1) {
			if (maxBounds != null) {
				size.x= Math.min(size.x, maxBounds.width);
				size.y= Math.min(size.y, maxBounds.height);
			}

			// Enforce an absolute minimal size
			size.x= Math.max(size.x, 30);
			size.y= Math.max(size.y, 30);
		}

		return size;
	}

	/**
	 * Sets the prefix completion property. If enabled, content assist delegates completion to
	 * prefix completion.
	 *
	 * @param enabled <code>true</code> to enable prefix completion, <code>false</code> to
	 *        disable
	 */
	public void enablePrefixCompletion(boolean enabled) {
		fIsPrefixCompletionEnabled= enabled;
	}

	/**
	 * Returns the prefix completion state.
	 *
	 * @return <code>true</code> if prefix completion is enabled, <code>false</code> otherwise
	 * @since 3.2
	 */
	boolean isPrefixCompletionEnabled() {
		return fIsPrefixCompletionEnabled;
	}

	/**
	 * Returns whether the content assistant proposal popup has the focus.
	 *
	 * @return <code>true</code> if the proposal popup has the focus
	 * @since 3.0
	 */
	public boolean hasProposalPopupFocus() {
		return fProposalPopup.hasFocus();
	}

	@Override
	public void addCompletionListener(ICompletionListener listener) {
		Assert.isLegal(listener != null);
		fCompletionListeners.add(listener);
	}

	@Override
	public void removeCompletionListener(ICompletionListener listener) {
		fCompletionListeners.remove(listener);
	}

	/**
	 * Fires a session begin event to all registered {@link ICompletionListener}s.
	 *
	 * @param isAutoActivated  <code>true</code> if this session was triggered by auto activation
	 * @since 3.2
	 */
	void fireSessionBeginEvent(boolean isAutoActivated) {
		if (fContentAssistSubjectControlAdapter != null && !isProposalPopupActive()) {
			Set<IContentAssistProcessor> processors= getProcessors(fContentAssistSubjectControlAdapter, fContentAssistSubjectControlAdapter.getSelectedRange().x);
			if (processors != null) {
				processors.forEach(processor -> {
					ContentAssistEvent event= new ContentAssistEvent(this, processor, isAutoActivated);
					for (ICompletionListener listener : fCompletionListeners) {
						listener.assistSessionStarted(event);
					}
				});
			}
		}
	}

	/**
	 * Fires a session restart event to all registered {@link ICompletionListener}s.
	 *
	 * @since 3.4
	 */
	void fireSessionRestartEvent() {
		if (fContentAssistSubjectControlAdapter != null) {
			Set<IContentAssistProcessor> processors= getProcessors(fContentAssistSubjectControlAdapter, fContentAssistSubjectControlAdapter.getSelectedRange().x);
			if (processors != null) {
				processors.forEach(processor -> {
					ContentAssistEvent event= new ContentAssistEvent(this, processor);
					for (ICompletionListener listener : fCompletionListeners) {
						if (listener instanceof ICompletionListenerExtension)
							((ICompletionListenerExtension)listener).assistSessionRestarted(event);
					}
				});
			}
		}
	}

	/**
	 * Fires a session end event to all registered {@link ICompletionListener}s.
	 *
	 * @since 3.2
	 */
	void fireSessionEndEvent() {
		if (fContentAssistSubjectControlAdapter != null) {
			Set<IContentAssistProcessor> processors= getProcessors(fContentAssistSubjectControlAdapter, fContentAssistSubjectControlAdapter.getSelectedRange().x);
			if (processors != null) {
				processors.forEach(processor -> {
					ContentAssistEvent event= new ContentAssistEvent(this, processor);
					for (ICompletionListener listener : fCompletionListeners) {
						listener.assistSessionEnded(event);
					}
				});
			}
		}
	}

	@Override
	public void setRepeatedInvocationMode(boolean cycling) {
		fIsRepetitionMode= cycling;
	}

	/**
	 * Returns <code>true</code> if repeated invocation mode is enabled, <code>false</code>
	 * otherwise.
	 *
	 * @return <code>true</code> if repeated invocation mode is enabled, <code>false</code>
	 *         otherwise
	 * @since 3.2
	 */
	boolean isRepeatedInvocationMode() {
		return fIsRepetitionMode;
	}

	@Override
	public void setShowEmptyList(boolean showEmpty) {
		fShowEmptyList= showEmpty;
	}

	/**
	 * Returns <code>true</code> if empty lists should be displayed, <code>false</code>
	 * otherwise.
	 *
	 * @return <code>true</code> if empty lists should be displayed, <code>false</code>
	 *         otherwise
	 * @since 3.2
	 */
	boolean isShowEmptyList() {
		return fShowEmptyList;
	}

	@Override
	public void setStatusLineVisible(boolean show) {
		fIsStatusLineVisible= show;
		if (fProposalPopup != null)
			fProposalPopup.setStatusLineVisible(show);
	}

	/**
	 * Returns <code>true</code> if a message line should be displayed, <code>false</code>
	 * otherwise.
	 *
	 * @return <code>true</code> if a message line should be displayed, <code>false</code>
	 *         otherwise
	 * @since 3.2
	 */
	boolean isStatusLineVisible() {
		return fIsStatusLineVisible;
	}

	@Override
	public void setStatusMessage(String message) {
		Assert.isLegal(message != null);
		fMessage= message;
		if (fProposalPopup != null)
			fProposalPopup.setMessage(message);
	}

	/**
	 * Returns the affordance caption for the cycling affordance at the bottom of the pop-up.
	 *
	 * @return the affordance caption for the cycling affordance at the bottom of the pop-up
	 * @since 3.2
	 */
	String getStatusMessage() {
		return fMessage;
	}

	@Override
	public void setEmptyMessage(String message) {
		Assert.isLegal(message != null);
		if (fProposalPopup != null)
			fProposalPopup.setEmptyMessage(message);
	}

	/**
	 * Fires a selection event, see {@link ICompletionListener}.
	 *
	 * @param proposal the selected proposal, possibly <code>null</code>
	 * @param smartToggle true if the smart toggle is on
	 * @since 3.2
	 */
	void fireSelectionEvent(ICompletionProposal proposal, boolean smartToggle) {
		for (ICompletionListener listener : fCompletionListeners) {
			listener.selectionChanged(proposal, smartToggle);
		}
	}

	/**
	 * Fires an event after applying a proposal, see {@link ICompletionListenerExtension2}.
	 *
	 * @param proposal the applied proposal
	 * @since 3.8
	 */
	void fireAppliedEvent(ICompletionProposal proposal) {
		for (ICompletionListener listener : fCompletionListeners) {
			if (listener instanceof ICompletionListenerExtension2)
				((ICompletionListenerExtension2)listener).applied(proposal);
		}
	}

	/*
	 * @see org.eclipse.jface.text.contentassist.IContentAssistantExtension3#setInvocationTrigger(org.eclipse.jface.bindings.keys.KeySequence)
	 * @since 3.2
	 */
	@Override
	public void setRepeatedInvocationTrigger(KeySequence sequence) {
		fRepeatedInvocationKeySequence= sequence;
	}

	/**
	 * Returns the repeated invocation key sequence.
	 *
	 * @return the repeated invocation key sequence or <code>null</code>, if none
	 * @since 3.2
	 */
	KeySequence getRepeatedInvocationKeySequence() {
		return fRepeatedInvocationKeySequence;
	}

	/**
	 * Returns whether proposal popup is active.
	 *
	 * @return <code>true</code> if the proposal popup is active, <code>false</code> otherwise
	 * @since 3.4
	 */
	protected boolean isProposalPopupActive(){
		return fProposalPopup != null && fProposalPopup.isActive();
	}

	/**
	 * Returns whether the context information popup is active.
	 *
	 * @return <code>true</code> if the context information popup is active, <code>false</code> otherwise
	 * @since 3.4
	 */
	protected boolean isContextInfoPopupActive(){
		return fContextInfoPopup != null && fContextInfoPopup.isActive();
	}

	/**
	 * {@inheritDoc}
	 *
	 * @since 3.4
	 */
	@Override
	public final IHandler getHandler(String commandId) {
		if (fHandlers == null)
			throw new IllegalStateException();

		IHandler handler= fHandlers.get(commandId);
		if (handler != null)
			return handler;

		Assert.isLegal(false);
		return null;
	}

	/**
	 * Registers the given handler under the given command identifier.
	 *
	 * @param commandId the command identifier
	 * @param handler the handler
	 * @since 3.4
	 */
	protected final void registerHandler(String commandId, IHandler handler) {
		if (fHandlers == null)
			fHandlers= new HashMap<>(2);
		fHandlers.put(commandId, handler);
	}

	/**
	 * Tells whether the support for colored labels is enabled.
	 *
	 * @return <code>true</code> if the support for colored labels is enabled, <code>false</code> otherwise
	 * @since 3.4
	 */
	boolean isColoredLabelsSupportEnabled() {
		return fIsColoredLabelsSupportEnabled;
	}

	/**
	 * Enables the support for colored labels in the proposal popup.
	 * <p>Completion proposals can implement {@link ICompletionProposalExtension6}
	 * to provide colored proposal labels.</p>
	 *
	 * @param isEnabled if <code>true</code> the support for colored labels is enabled in the proposal popup
	 * @since 3.4
	 */
	public void enableColoredLabels(boolean isEnabled) {
		fIsColoredLabelsSupportEnabled= isEnabled;
	}

	/**
	 * Sets the proposal sorter.
	 *
	 * @param sorter the sorter to be used, or <code>null</code> if no sorting is requested
	 * @since 3.8
	 */
	public void setSorter(ICompletionProposalSorter sorter) {
		fSorter= sorter;
		if (fProposalPopup != null) {
			fProposalPopup.setSorter(fSorter);
		}
	}

	/**
	 * Returns whether completion trigger char are enabled. If false, completion proposal trigger
	 * chars are ignored and only Enter key can be used to select a proposal.
	 *
	 * @return whether completion trigger char are enabled.
	 * @see ICompletionProposalExtension#getTriggerCharacters()
	 * @since 3.15
	 */
	public boolean isCompletionProposalTriggerCharsEnabled() {
		return fCompletionProposalTriggerCharsEnabled;
	}

	/**
	 * Set whether completion trigger chars are enabled. If set to false, completion proposal
	 * trigger chars are ignored and only Enter key can be used to select a proposal.
	 *
	 * @param enable whether current content assistant should consider completion trigger chars.
	 * @see ICompletionProposalExtension#getTriggerCharacters()
	 * @since 3.15
	 */
	public void enableCompletionProposalTriggerChars(boolean enable) {
		fCompletionProposalTriggerCharsEnabled= enable;
	}

	boolean isAutoActivation() {
		return fIsAutoActivated;
	}

}
