/*******************************************************************************
 * Copyright (c) 2011 Laurent CARON.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Laurent CARON (laurent.caron@gmail.com) - initial API and implementation
 *******************************************************************************/

package org.mihalis.opal.multiChoice;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
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.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.mihalis.opal.utils.ResourceManager;
import org.mihalis.opal.utils.SimpleSelectionAdapter;

/**
 * The MultiChoice class represents a selectable user interface object that combines a read-only text-field and a set of checkboxes.
 * 
 * <p>
 * Note that although this class is a subclass of <code>Composite</code>, it does not make sense to add children to it, or set a layout on it.
 * </p>
 * <dl>
 * <dt><b>Styles:</b>
 * <dd>NONE</dd>
 * <dt><b>Events:</b>
 * <dd>Selection</dd>
 * </dl>
 * 
 * @param <T> Class of objects represented by this widget
 */
public class MultiChoice<T> extends Composite {

	/** The text. */
	private Text text;
	
	/** The arrow. */
	private Button arrow;
	
	/** The popup. */
	private Shell popup;
	
	/** The scrolled composite. */
	private ScrolledComposite scrolledComposite;
	
	/** The filter. */
	private Listener listener, filter;
	
	/** The number of columns. */
	private int numberOfColumns = 2;
	
	/** The elements. */
	private List<T> elements;
	
	/** The selection. */
	private Set<T> selection;
	
	/** The checkboxes. */
	private List<Button> checkboxes;
	
	/** The has focus. */
	private boolean hasFocus;
	
	/** The selection listener. */
	private MultiChoiceSelectionListener<T> selectionListener;
	
	/** The last modified. */
	private T lastModified;
	
	/** The background. */
	private Color foreground, background;
	
	/** The font. */
	private Font font;
	
	/** The separator. */
	private String separator;
	
	/** The label provider. */
	private MultiChoiceLabelProvider labelProvider;
	
	/** The preferred height of popup. */
	private int preferredHeightOfPopup;

	/**
	 * Constructs a new instance of this class given its parent.
	 * 
	 * @param parent a widget which will be the parent of the new instance (cannot be null)
	 * @param style not used
	 * 
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
	 *                </ul>
	 * @exception SWTException <ul>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
	 *                </ul>
	 */
	public MultiChoice(final Composite parent, final int style) {
		this(parent, style, null);
	}

	/**
	 * Constructs a new instance of this class given its parent.
	 * 
	 * @param parent a widget which will be the parent of the new instance (cannot be null)
	 * @param style not used
	 * @param elements list of elements displayed by this widget
	 * 
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
	 *                </ul>
	 * @exception SWTException <ul>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
	 *                </ul>
	 */
	public MultiChoice(final Composite parent, final int style, final List<T> elements) {
		super(parent, style);

		final GridLayout gridLayout = new GridLayout(2, false);
		gridLayout.horizontalSpacing = gridLayout.verticalSpacing = gridLayout.marginWidth = gridLayout.marginHeight = 0;
		this.setLayout(gridLayout);

		int readOnlyStyle;
		if ((style & SWT.READ_ONLY) == SWT.READ_ONLY) {
			readOnlyStyle = SWT.READ_ONLY;
		} else {
			readOnlyStyle = SWT.NONE;
		}

		this.text = new Text(this, SWT.SINGLE | readOnlyStyle | SWT.BORDER);
		this.text.setBackground(this.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
		this.text.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));

		this.arrow = new Button(this, SWT.ARROW | SWT.RIGHT);
		this.arrow.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false));

		createGlobalListener();
		addListeners();

		this.filter = new Listener() {
			@Override
			public void handleEvent(final Event event) {
				final Shell shell = ((Control) event.widget).getShell();
				if (shell == MultiChoice.this.getShell()) {
					handleFocusEvents(SWT.FocusOut);
				}
			}
		};

		this.selection = new LinkedHashSet<T>();
		this.elements = elements;
		this.separator = ",";
		this.labelProvider = new MultiChoiceDefaultLabelProvider();

		createPopup();
		setLabel();
	}

	/**
	 * Creates the global listener.
	 */
	private void createGlobalListener() {
		this.listener = new Listener() {
			@Override
			public void handleEvent(final Event event) {
				if (MultiChoice.this.popup == event.widget) {
					handlePopupEvent(event);
					return;
				}

				if (MultiChoice.this.arrow == event.widget) {
					handleButtonEvent(event);
					return;
				}

				if (MultiChoice.this == event.widget) {
					handleMultiChoiceEvents(event);
					return;
				}

				if (getShell() == event.widget) {
					getDisplay().asyncExec(new Runnable() {
						@Override
						public void run() {
							if (isDisposed()) {
								return;
							}
							handleFocusEvents(SWT.FocusOut);
						}
					});
				}
			}
		};
	}

	/**
	 * Adds the listeners.
	 */
	private void addListeners() {

		final int[] multiChoiceEvent = { SWT.Dispose, SWT.Move, SWT.Resize };
		for (final int element : multiChoiceEvent) {
			this.addListener(element, this.listener);
		}

		if ((getStyle() & SWT.READ_ONLY) == 0) {
			final Listener validationListener = new Listener() {

				@Override
				public void handleEvent(final Event event) {
					if (!MultiChoice.this.popup.isDisposed() && !MultiChoice.this.popup.isVisible()) {
						validateEntry();
					}
				}
			};
			this.text.addListener(SWT.FocusOut, validationListener);
		}

		final int[] buttonEvents = { SWT.Selection, SWT.FocusIn };
		for (final int buttonEvent : buttonEvents) {
			this.arrow.addListener(buttonEvent, this.listener);
		}
	}

	/**
	 * Validate entry.
	 */
	protected void validateEntry() {
		final String toValidate = this.text.getText();
		final String[] elementsToValidate = toValidate.split(this.separator);
		final List<String> fieldsInError = new ArrayList<String>();
		this.selection.clear();
		for (final String elementToValidate : elementsToValidate) {
			final String temp = elementToValidate.trim();
			if ("".equals(temp)) {
				continue;
			}

			final T entry = convertEntry(temp);

			if (entry == null) {
				fieldsInError.add(temp);
			} else {
				this.selection.add(entry);
			}
		}

		if (fieldsInError.size() == 0) {
			updateSelection();
			return;
		}

		final String messageToDisplay;
		if (fieldsInError.size() == 1) {
			messageToDisplay = String.format(ResourceManager.getLabel(ResourceManager.MULTICHOICE_MESSAGE), fieldsInError.get(0));
		} else {
			final StringBuilder sb = new StringBuilder();
			final Iterator<String> it = fieldsInError.iterator();
			while (it.hasNext()) {
				sb.append(it.next());
				if (it.hasNext()) {
					sb.append(",");
				}
			}
			messageToDisplay = String.format(ResourceManager.getLabel(ResourceManager.MULTICHOICE_MESSAGE_PLURAL), sb.toString());
		}
		getDisplay().asyncExec(new Runnable() {
			@Override
			public void run() {
				final MessageBox mb = new MessageBox(getShell(), SWT.OK | SWT.ICON_ERROR);
				mb.setMessage(messageToDisplay);
				mb.open();
				MultiChoice.this.text.forceFocus();
			}
		});

	}

	/**
	 * Convert entry.
	 *
	 * @param elementToValidate the element to validate
	 * @return the t
	 */
	private T convertEntry(final String elementToValidate) {
		for (final T elt : this.elements) {
			if (this.labelProvider.getText(elt).trim().equals(elementToValidate)) {
				return elt;
			}
		}
		return null;
	}

	/**
	 * Adds the argument to the end of the receiver's list.
	 *
	 * @param value the value
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the string is null</li>
	 *                </ul>
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been
	 *                disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
	 *                thread that created the receiver</li>
	 *                </ul>
	 */
	public void add(final T value) {
		checkWidget();
		if (value == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}

		if (this.elements == null) {
			this.elements = new ArrayList<T>();
		}
		this.elements.add(value);
		refresh();
	}

	/**
	 * Adds the argument to the receiver's list at the given zero-relative
	 * index.
	 *
	 * @param value the value
	 * @param index the index for the item
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the string is null</li>
	 *                <li>ERROR_INVALID_RANGE - if the index is not between 0
	 *                and the number of elements in the list minus 1 (inclusive)
	 *                </li>
	 *                </ul>
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been
	 *                disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
	 *                thread that created the receiver</li>
	 *                </ul>
	 */
	public void add(final T value, final int index) {
		checkWidget();
		checkNullElement();
		if (value == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}

		checkRange(index);

		this.elements.add(index, value);
		refresh();
	}

	/**
	 * Adds the argument to the end of the receiver's list.
	 * 
	 * @param values new items
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the string is null</li>
	 *                </ul>
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
	 *                </ul>
	 */
	public void addAll(final List<T> values) {
		checkWidget();
		if (values == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}

		if (this.elements == null) {
			this.elements = new ArrayList<T>();
		}
		this.elements.addAll(values);
		refresh();
	}

	/**
	 * Adds the argument to the end of the receiver's list.
	 * 
	 * @param values new items
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the string is null</li>
	 *                </ul>
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
	 *                </ul>
	 */
	public void addAll(final T[] values) {
		checkWidget();
		if (values == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}
		if (this.elements == null) {
			this.elements = new ArrayList<T>();
		}
		for (final T value : values) {
			this.elements.add(value);
		}
		refresh();
	}

	/**
	 * Returns the item at the given, zero-relative index in the receiver's list. Throws an exception if the index is out of range.
	 * 
	 * @param index the index of the item to return
	 * @return the item at the given index
	 * 
	 * @exception NullPointerException if there is no item in the receiver
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
	 *                </ul>
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
	 *                </ul>
	 */
	public T getItem(final int index) {
		checkWidget();
		checkNullElement();
		checkRange(index);

		return this.elements.get(index);
	}

	/**
	 * Returns the number of items contained in the receiver's list.
	 * 
	 * @return the number of items
	 * 
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
	 *                </ul>
	 */
	public int getItemCount() {
		checkWidget();
		if (this.elements == null) {
			return 0;
		}

		return this.elements.size();

	}

	/**
	 * Returns the list of items in the receiver's list.
	 * <p>
	 * Note: This is not the actual structure used by the receiver to maintain its list of items, so modifying the array will not affect the receiver.
	 * </p>
	 * 
	 * @return the items in the receiver's list
	 * 
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
	 *                </ul>
	 */
	public List<T> getItems() {
		checkWidget();
		if (this.elements == null) {
			return null;
		}
		return new ArrayList<T>(this.elements);
	}

	/**
	 * Removes the item from the receiver's list at the given zero-relative index.
	 * 
	 * @param index the index for the item
	 * @exception NullPointerException if there is no item in the receiver
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
	 *                </ul>
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
	 *                </ul>
	 */
	public void removeAt(final int index) {
		checkWidget();
		checkNullElement();
		checkRange(index);
		final Object removedElement = this.elements.remove(index);
		this.selection.remove(removedElement);
		refresh();
	}

	/**
	 * Searches the receiver's list starting at the first item until an item is found that is equal to the argument, and removes that item from the list.
	 * 
	 * @param object the item to remove
	 * @exception NullPointerException if there is no item in the receiver
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the object is null</li>
	 *                </ul>
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
	 *                </ul>
	 */
	public void remove(final T object) {
		if (object == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}
		checkWidget();
		checkNullElement();
		this.elements.remove(object);
		this.selection.remove(object);
		refresh();
	}

	/**
	 * Remove all items of the receiver.
	 *
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been
	 *                disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
	 *                thread that created the receiver</li>
	 *                </ul>
	 */
	public void removeAll() {
		checkWidget();
		checkNullElement();
		if (this.elements != null) {
			this.elements.clear();
		}
		this.selection.clear();
		refresh();
	}

	/**
	 * Sets the label provider.
	 *
	 * @param labelProvider the Label Provider to set
	 */
	public void setLabelProvider(final MultiChoiceLabelProvider labelProvider) {
		this.labelProvider = labelProvider;
	}

	/**
	 * Sets the selection of the receiver. If the item was already selected, it remains selected.
	 * 
	 * @param selection the new selection
	 * @exception NullPointerException if there is no item in the receiver
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the selection is null</li>
	 *                </ul>
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
	 *                </ul>
	 */
	public void setSelection(final Set<T> selection) {
		checkWidget();
		checkNullElement();
		if (selection == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}
		this.selection = selection;
		updateSelection();
	}

	/**
	 * Selects all selected items in the receiver's list.
	 * 
	 * @exception NullPointerException if there is no item in the receiver
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
	 *                </ul>
	 */
	public void selectAll() {
		checkWidget();
		checkNullElement();
		this.selection.addAll(this.elements);
		updateSelection();
	}

	/**
	 * Selects the item at the given zero-relative index in the receiver's list. If the item at the index was already selected, it remains selected.
	 * 
	 * @param index the index of the item to select
	 * @exception NullPointerException if there is no item in the receiver
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
	 *                </ul>
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
	 *                </ul>
	 */
	public void selectAt(final int index) {
		checkWidget();
		checkNullElement();
		checkRange(index);
		this.selection.add(this.elements.get(index));
		updateSelection();
	}

	/**
	 * Selects an item the receiver's list. If the item was already selected, it
	 * remains selected.
	 *
	 * @param value the value
	 * @exception NullPointerException if there is no item in the receiver
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the selection is null</li>
	 *                </ul>
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been
	 *                disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
	 *                thread that created the receiver</li>
	 *                </ul>
	 */
	public void select(final T value) {
		checkWidget();
		checkNullElement();
		if (!this.elements.contains(value)) {
			throw new IllegalArgumentException("Value not present in the widget");
		}
		this.selection.add(value);
		updateSelection();
	}

	/**
	 * Selects items in the receiver. If the items were already selected, they remain selected.
	 * 
	 * @param index the indexes of the items to select
	 * @exception NullPointerException if there is no item in the receiver
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the selection is null</li>
	 *                <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
	 *                </ul>
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
	 *                </ul>
	 */
	public void setSelectedIndex(final int[] index) {
		checkWidget();
		checkNullElement();
		for (final int i : index) {
			checkRange(i);
			this.selection.add(this.elements.get(i));
		}
		updateSelection();
	}

	/**
	 * Returns the zero-relative indices of the items which are currently selected in the receiver. The order of the indices is unspecified. The array is empty if no items are selected.
	 * <p>
	 * Note: This is not the actual structure used by the receiver to maintain its selection, so modifying the array will not affect the receiver.
	 * </p>
	 * 
	 * @return the array of indices of the selected items
	 * @exception NullPointerException if there is no item in the receiver
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
	 *                </ul>
	 */
	public int[] getSelectedIndex() {
		checkWidget();
		checkNullElement();
		final List<Integer> selectedIndex = new ArrayList<Integer>();
		for (int i = 0; i < this.elements.size(); i++) {
			if (this.selection.contains(this.elements.get(i))) {
				selectedIndex.add(i);
			}
		}

		final int[] returned = new int[selectedIndex.size()];
		for (int i = 0; i < selectedIndex.size(); i++) {
			returned[i] = selectedIndex.get(i);
		}

		return returned;
	}

	/**
	 * Returns an array of <code>Object</code>s that are currently selected in the receiver. The order of the items is unspecified. An empty array indicates that no items are selected.
	 * <p>
	 * Note: This is not the actual structure used by the receiver to maintain its selection, so modifying the array will not affect the receiver.
	 * </p>
	 * 
	 * @return an array representing the selection
	 * @exception NullPointerException if there is no item in the receiver
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
	 *                </ul>
	 */
	public List<T> getSelection() {
		checkWidget();
		checkNullElement();
		return new ArrayList<T>(this.selection);
	}

	/**
	 * Deselects the item at the given zero-relative index in the receiver's list. If the item at the index was already deselected, it remains deselected. Indices that are out of range are ignored.
	 * 
	 * @param index the index of the item to deselect
	 * @exception NullPointerException if there is no item in the receiver
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
	 *                </ul>
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
	 *                </ul>
	 */
	public void deselectAt(final int index) {
		this.selection.remove(getItem(index));
		updateSelection();
	}

	/**
	 * Deselects the item in the receiver's list. If the item at the index was already deselected, it remains deselected.
	 * 
	 * @param value the item to deselect
	 * @exception NullPointerException if there is no item in the receiver
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
	 *                </ul>
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
	 *                </ul>
	 */
	public void deselect(final T value) {
		checkWidget();
		checkNullElement();
		this.selection.remove(value);
		updateSelection();
	}

	/**
	 * Deselects all items in the receiver's list.
	 *
	 * @exception NullPointerException if there is no item in the receiver
	 * @exception SWTException <ul>
	 *                <li>ERROR_WIDGET_DISPOSED - if the receiver has been
	 *                disposed</li>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
	 *                thread that created the receiver</li>
	 *                </ul>
	 */
	public void deselectAll() {
		checkWidget();
		checkNullElement();
		this.selection.clear();
		updateSelection();
	}

	/**
	 * Gets the number of columns.
	 *
	 * @return the number of columns
	 */
	public int getNumberOfColumns() {
		checkWidget();
		return this.numberOfColumns;
	}

	/**
	 * Sets the number of columns.
	 *
	 * @param numberOfColumns the number of columns
	 */
	public void setNumberOfColumns(final int numberOfColumns) {
		checkWidget();
		this.numberOfColumns = numberOfColumns;
		this.popup.dispose();
		this.popup = null;
		createPopup();
	}

	/**
	 * Gets the separator.
	 *
	 * @return the separator used in the text field. Default value is ","
	 */
	public String getSeparator() {
		return this.separator;
	}

	/**
	 * Sets the separator.
	 *
	 * @param separator the new value of the separator
	 */
	public void setSeparator(final String separator) {
		this.separator = separator;
	}

	/**
	 * Gets the foreground.
	 *
	 * @return the foreground
	 * @see org.eclipse.swt.widgets.Control#getForeground()
	 */
	@Override
	public Color getForeground() {
		return this.foreground;
	}

	/**
	 * Sets the foreground.
	 *
	 * @param foreground the new foreground
	 * @see org.eclipse.swt.widgets.Control#setForeground(org.eclipse.swt.graphics.Color)
	 */
	@Override
	public void setForeground(final Color foreground) {
		this.foreground = foreground;
	}

	/**
	 * Gets the background.
	 *
	 * @return the background
	 * @see org.eclipse.swt.widgets.Control#getBackground()
	 */
	@Override
	public Color getBackground() {
		return this.background;
	}

	/**
	 * Sets the background.
	 *
	 * @param background the new background
	 * @see org.eclipse.swt.widgets.Control#setBackground(org.eclipse.swt.graphics.Color)
	 */
	@Override
	public void setBackground(final Color background) {
		this.background = background;
	}

	/**
	 * Gets the font.
	 *
	 * @return the font
	 * @see org.eclipse.swt.widgets.Control#getFont()
	 */
	@Override
	public Font getFont() {
		return this.font;
	}

	/**
	 * Sets the font.
	 *
	 * @param font the new font
	 * @see org.eclipse.swt.widgets.Control#setFont(org.eclipse.swt.graphics.Font)
	 */
	@Override
	public void setFont(final Font font) {
		this.font = font;
	}

	/**
	 * Refresh the widget (after the add of a new element for example).
	 */
	public void refresh() {
		checkWidget();
		this.popup.dispose();
		this.popup = null;
		createPopup();
		updateSelection();
	}

	/**
	 * Compute size.
	 *
	 * @param wHint the w hint
	 * @param hHint the h hint
	 * @param changed the changed
	 * @return the point
	 * @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)
	 */
	@Override
	public Point computeSize(final int wHint, final int hHint, final boolean changed) {
		checkWidget();
		int width = 0, height = 0;

		final GC gc = new GC(this.text);
		final int spacer = gc.stringExtent(" ").x;
		final int textWidth = gc.stringExtent(this.text.getText()).x;
		gc.dispose();
		final Point textSize = this.text.computeSize(SWT.DEFAULT, SWT.DEFAULT, changed);
		final Point arrowSize = this.arrow.computeSize(SWT.DEFAULT, SWT.DEFAULT, changed);
		final int borderWidth = getBorderWidth();

		height = Math.max(textSize.y, arrowSize.y);
		width = textWidth + 2 * spacer + arrowSize.x + 2 * borderWidth;
		if (wHint != SWT.DEFAULT) {
			width = wHint;
		}
		if (hHint != SWT.DEFAULT) {
			height = hHint;
		}
		return new Point(width + 2 * borderWidth, height + 2 * borderWidth);
	}

	/**
	 * Sets the enabled.
	 *
	 * @param enabled the new enabled
	 * @see org.eclipse.swt.widgets.Control#setEnabled(boolean)
	 */
	@Override
	public void setEnabled(final boolean enabled) {
		checkWidget();
		this.arrow.setEnabled(enabled);
		this.text.setEnabled(enabled);
		super.setEnabled(enabled);
	}

	/**
	 * Sets the tool tip text.
	 *
	 * @param txt the new tool tip text
	 * @see org.eclipse.swt.widgets.Control#setToolTipText(java.lang.String)
	 */
	@Override
	public void setToolTipText(final String txt) {
		checkWidget();
		this.text.setToolTipText(txt);
	}

	/**
	 * Gets the selection listener.
	 *
	 * @return the selection listener
	 */
	public SelectionListener getSelectionListener() {
		checkWidget();
		return this.selectionListener;
	}

	/**
	 * Sets the selection listener.
	 *
	 * @param selectionListener the new selection listener
	 */
	public void setSelectionListener(final MultiChoiceSelectionListener<T> selectionListener) {
		checkWidget();
		this.selectionListener = selectionListener;
		refresh();
	}

	/**
	 * Update the selection.
	 */
	public void updateSelection() {
		checkWidget();
		if (isDisposed()) {
			return;
		}

		if (this.popup == null || this.popup.isDisposed() || this.checkboxes == null) {
			return;
		}

		for (int i = 0; i < this.checkboxes.size(); i++) {
			final Button currentButton = this.checkboxes.get(i);
			if (!currentButton.isDisposed()) {
				final Object content = currentButton.getData();
				currentButton.setSelection(this.selection.contains(content));
			}
		}
		setLabel();

	}

	/**
	 * Gets the last modified.
	 *
	 * @return the last modified item
	 */
	T getLastModified() {
		return this.lastModified;
	}

	/**
	 * Gets the popup.
	 *
	 * @return the popup
	 */
	Shell getPopup() {
		return this.popup;
	}

	/**
	 * Create the popup that contains all checkboxes.
	 */
	private void createPopup() {
		this.popup = new Shell(getShell(), SWT.NO_TRIM | SWT.ON_TOP);
		this.popup.setLayout(new FillLayout());

		final int[] popupEvents = { SWT.Close, SWT.Deactivate, SWT.Dispose };
		for (final int popupEvent : popupEvents) {
			this.popup.addListener(popupEvent, this.listener);
		}

		if (this.elements == null) {
			return;
		}

		this.scrolledComposite = new ScrolledComposite(this.popup, SWT.BORDER | SWT.V_SCROLL);
		final Composite content = new Composite(this.scrolledComposite, SWT.NONE);
		content.setLayout(new GridLayout(this.numberOfColumns, true));

		this.checkboxes = new ArrayList<Button>(this.elements.size());
		for (final T o : this.elements) {
			final Button checkBoxButton = new Button(content, SWT.CHECK);

			if (this.font != null) {
				checkBoxButton.setFont(this.font);
			}
			if (this.foreground != null) {
				checkBoxButton.setForeground(this.foreground);
			}
			if (this.background != null) {
				checkBoxButton.setBackground(this.background);
			}

			checkBoxButton.setData(o);
			checkBoxButton.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, false, false));
			checkBoxButton.setText(this.labelProvider.getText(o));
			checkBoxButton.addSelectionListener(new SimpleSelectionAdapter() {
				@Override
				public void handle(final SelectionEvent e) {
					if (checkBoxButton.getSelection()) {
						MultiChoice.this.selection.add(o);
					} else {
						MultiChoice.this.selection.remove(o);
					}
					MultiChoice.this.lastModified = o;
					setLabel();
				}
			});

			if (this.selectionListener != null) {
				checkBoxButton.addSelectionListener(this.selectionListener);
			}

			checkBoxButton.setSelection(this.selection.contains(o));
			this.checkboxes.add(checkBoxButton);
		}

		this.scrolledComposite.setContent(content);
		this.scrolledComposite.setExpandHorizontal(false);
		this.scrolledComposite.setExpandVertical(true);
		content.pack();
		this.preferredHeightOfPopup = content.getSize().y;
	}

	/**
	 * Set the value of the label, based on the selected items.
	 */
	private void setLabel() {
		if (this.checkboxes == null) {
			this.text.setText("");
			return;
		}

		final List<String> values = new ArrayList<String>();
		for (final Button current : this.checkboxes) {
			if (current.getSelection()) {
				values.add(current.getText());
			}
		}

		final StringBuilder sb = new StringBuilder();
		final Iterator<String> it = values.iterator();
		while (it.hasNext()) {
			sb.append(it.next());
			if (it.hasNext()) {
				sb.append(this.separator);
			}
		}

		this.text.setText(sb.toString());
	}

	/**
	 * Handle a focus event.
	 *
	 * @param type type of the event to handle
	 */
	private void handleFocusEvents(final int type) {
		if (isDisposed()) {
			return;
		}
		switch (type) {
			case SWT.FocusIn: {
				if (this.hasFocus) {
					return;
				}
				this.hasFocus = true;
				final Shell shell = getShell();
				shell.removeListener(SWT.Deactivate, this.listener);
				shell.addListener(SWT.Deactivate, this.listener);
				final Display display = getDisplay();
				display.removeFilter(SWT.FocusIn, this.filter);
				display.addFilter(SWT.FocusIn, this.filter);
				final Event e = new Event();
				notifyListeners(SWT.FocusIn, e);
				break;
			}
			case SWT.FocusOut: {
				if (!this.hasFocus) {
					return;
				}
				final Control focusControl = getDisplay().getFocusControl();
				if (focusControl == this.arrow) {
					return;
				}
				this.hasFocus = false;
				final Shell shell = getShell();
				shell.removeListener(SWT.Deactivate, this.listener);
				final Display display = getDisplay();
				display.removeFilter(SWT.FocusIn, this.filter);
				final Event e = new Event();
				notifyListeners(SWT.FocusOut, e);
				break;
			}
		}
	}

	/**
	 * Handle a multichoice event.
	 *
	 * @param event event to handle
	 */
	private void handleMultiChoiceEvents(final Event event) {
		switch (event.type) {
			case SWT.Dispose:
				if (this.popup != null && !this.popup.isDisposed()) {
					this.popup.dispose();
				}
				final Shell shell = getShell();
				shell.removeListener(SWT.Deactivate, this.listener);
				final Display display = getDisplay();
				display.removeFilter(SWT.FocusIn, this.filter);
				this.popup = null;
				this.arrow = null;
				break;
			case SWT.Move:
				changeVisibilityOfPopupWindow(false);
				break;
			case SWT.Resize:
				if (isDropped()) {
					changeVisibilityOfPopupWindow(false);
				}
				break;
		}

	}

	/**
	 * Handle a button event.
	 *
	 * @param event event to hangle
	 */
	private void handleButtonEvent(final Event event) {
		switch (event.type) {
			case SWT.FocusIn: {
				handleFocusEvents(SWT.FocusIn);
				break;
			}
			case SWT.Selection: {
				changeVisibilityOfPopupWindow(!isDropped());
				break;
			}
		}
	}

	/**
	 * Checks if is dropped.
	 *
	 * @return <code>true</code> if the popup is visible and not dropped,
	 *         <code>false</code> otherwise
	 */
	private boolean isDropped() {
		return !this.popup.isDisposed() && this.popup.getVisible();
	}

	/**
	 * Handle a popup event.
	 *
	 * @param event event to handle
	 */
	private void handlePopupEvent(final Event event) {
		switch (event.type) {
			case SWT.Close:
				event.doit = false;
				changeVisibilityOfPopupWindow(false);
				break;
			case SWT.Deactivate:
				changeVisibilityOfPopupWindow(false);
				break;
			case SWT.Dispose:
				if (this.checkboxes != null) {
					this.checkboxes.clear();
				}
				this.checkboxes = null;
				break;
		}

	}

	/**
	 * Display/Hide the popup window.
	 *
	 * @param show if <code>true</code>, displays the popup window. If
	 *            <code>false</code>, hide the popup window
	 */
	private void changeVisibilityOfPopupWindow(final boolean show) {
		if (show == isDropped()) {
			return;
		}

		if (!show) {
			this.popup.setVisible(false);
			if (!isDisposed()) {
				this.text.setFocus();
			}
			return;
		}

		if (getShell() != this.popup.getParent()) {
			this.popup.dispose();
			this.popup = null;
			createPopup();
		}

		final Point arrowRect = this.arrow.toDisplay(this.arrow.getSize().x - 5, this.arrow.getSize().y + this.arrow.getBorderWidth() - 3);
		int x = arrowRect.x;
		int y = arrowRect.y;

		final Rectangle displayRect = getMonitor().getClientArea();
		final Rectangle parentRect = getDisplay().map(getParent(), null, getBounds());
		this.popup.pack();

		final int width = this.popup.getBounds().width;

		final int maxHeight = (2 * displayRect.height / 3);
		int height = this.popup.getBounds().height;

		if (height > maxHeight) {
			height = maxHeight;
			this.popup.setSize(width, height);
			this.scrolledComposite.setMinHeight(this.preferredHeightOfPopup);
			this.popup.layout(true);
		}

		if (y + height > displayRect.y + displayRect.height) {
			y = parentRect.y - height;
			if (y < 0) {
				height += y;
				y = parentRect.y - height + 5;
				this.popup.setSize(width, height);
				this.scrolledComposite.setMinHeight(this.preferredHeightOfPopup);
				this.popup.layout(true);
			}
		}
		if (x + width > displayRect.x + displayRect.width) {
			x = displayRect.x + displayRect.width - width;
		}

		this.popup.setLocation(x, y);
		this.popup.setVisible(true);
		this.popup.setFocus();
	}

	/**
	 * Check if the elements attributes is not null.
	 *
	 * @exception NullPointerException if there is no item in the receiver
	 */
	private void checkNullElement() {
		if (this.elements == null) {
			throw new NullPointerException("There is no element associated to this widget");
		}
	}

	/**
	 * Check range.
	 *
	 * @param index the index
	 * @throws NullPointerException the null pointer exception
	 * @throws IllegalArgumentException the illegal argument exception
	 */
	private void checkRange(final int index) throws NullPointerException {
		checkNullElement();
		if (index < 0 || index >= this.elements.size()) {
			SWT.error(SWT.ERROR_INVALID_RANGE);
		}
	}

}
