/*******************************************************************************
 * 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 at gmail dot com) - initial API and implementation
 *******************************************************************************/
package org.mihalis.opal.itemSelector;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
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.Event;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.mihalis.opal.itemSelector.DLItem.LAST_ACTION;
import org.mihalis.opal.utils.SWTGraphicUtil;
import org.mihalis.opal.utils.SimpleSelectionAdapter;

/**
 * Instances of this class are controls that allow the user to select multiple
 * elements.
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>(none)</dd>
 * <dt><b>Events:</b></dt>
 * <dd>Selection</dd>
 * </dl>
 */

public class DualList extends Composite {

	/** The Constant DOUBLE_DOWN_IMAGE. */
	private static final String DOUBLE_DOWN_IMAGE = "double_down.png";
	
	/** The Constant DOUBLE_UP_IMAGE. */
	private static final String DOUBLE_UP_IMAGE = "double_up.png";
	
	/** The Constant DOUBLE_LEFT_IMAGE. */
	private static final String DOUBLE_LEFT_IMAGE = "double_left.png";
	
	/** The Constant DOUBLE_RIGHT_IMAGE. */
	private static final String DOUBLE_RIGHT_IMAGE = "double_right.png";
	
	/** The Constant ARROW_DOWN_IMAGE. */
	private static final String ARROW_DOWN_IMAGE = "arrow_down.png";
	
	/** The Constant ARROW_LEFT_IMAGE. */
	private static final String ARROW_LEFT_IMAGE = "arrow_left.png";
	
	/** The Constant ARROW_UP_IMAGE. */
	private static final String ARROW_UP_IMAGE = "arrow_up.png";
	
	/** The Constant ARROW_RIGHT_IMAGE. */
	private static final String ARROW_RIGHT_IMAGE = "arrow_right.png";

	/** The items. */
	private final List<DLItem> items;
	
	/** The selection. */
	private final List<DLItem> selection;

	/** The items table. */
	private Table itemsTable;
	
	/** The selection table. */
	private Table selectionTable;

	/** The selection listeners. */
	private List<SelectionListener> selectionListeners;
	
	/** The selection change listeners. */
	private List<SelectionChangeListener> selectionChangeListeners;

	/**
	 * Constructs a new instance of this class given its parent and a style
	 * value describing its behavior and appearance.
	 * <p>
	 * The style value is either one of the style constants defined in class
	 * <code>SWT</code> which is applicable to instances of this class, or must
	 * be built by <em>bitwise OR</em>'ing together (that is, using the
	 * <code>int</code> "|" operator) two or more of those <code>SWT</code>
	 * style constants. The class description lists the style constants that are
	 * applicable to the class. Style bits are also inherited from superclasses.
	 * </p>
	 *
	 * @param parent a composite control which will be the parent of the new
	 *            instance (cannot be null)
	 * @param style the style of control to construct
	 *
	 * @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 DualList(final Composite parent, final int style) {
		super(parent, style);
		items = new ArrayList<DLItem>();
		selection = new ArrayList<DLItem>();

		setLayout(new GridLayout(4, false));
		createItemsTable();
		createButtonSelectAll();
		createSelectionTable();
		createButtonMoveFirst();
		createButtonSelect();
		createButtonMoveUp();
		createButtonDeselect();
		createButtonMoveDown();
		createButtonDeselectAll();
		createButtonMoveLast();
	}

	/**
	 * Creates the items table.
	 */
	private void createItemsTable() {
		itemsTable = createTable();
		itemsTable.addMouseListener(new MouseAdapter() {
			/**
			 * @see org.eclipse.swt.events.MouseAdapter#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
			 */
			@Override
			public void mouseDoubleClick(final MouseEvent event) {
				DualList.this.selectItem();
			}
		});
	}

	/**
	 * Creates the table.
	 *
	 * @return a table that will contain data
	 */
	private Table createTable() {
		final Table table = new Table(this, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
		table.setLinesVisible(false);
		table.setHeaderVisible(false);
		final GridData gd = new GridData(GridData.FILL, GridData.FILL, true, true, 1, 4);
		gd.widthHint = 200;
		table.setLayoutData(gd);
//		new TableColumn(table, SWT.CENTER);
//		new TableColumn(table, SWT.LEFT);
		table.setData(-1);
		return table;
	}

	/**
	 * Creates the button select all.
	 */
	private void createButtonSelectAll() {
		final Button buttonSelectAll = createButton(DOUBLE_RIGHT_IMAGE, true, GridData.END);
		buttonSelectAll.addSelectionListener(new SimpleSelectionAdapter() {
			/**
			 * @see org.mihalis.opal.utils.SimpleSelectionAdapter#handle(org.eclipse.swt.events.SelectionEvent)
			 */
			@Override
			public void handle(final SelectionEvent e) {
				DualList.this.selectAll();
			}
		});
	}

	/**
	 * Creates the selection table.
	 */
	private void createSelectionTable() {
		selectionTable = createTable();
		selectionTable.addMouseListener(new MouseAdapter() {
			/**
			 * @see org.eclipse.swt.events.MouseAdapter#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
			 */
			@Override
			public void mouseDoubleClick(final MouseEvent event) {
				DualList.this.deselectItem();
			}
		});
	}

	/**
	 * Creates the button move first.
	 */
	private void createButtonMoveFirst() {
		final Button buttonMoveFirst = createButton(DOUBLE_UP_IMAGE, true, GridData.END);
		buttonMoveFirst.addSelectionListener(new SimpleSelectionAdapter() {
			/**
			 * @see org.mihalis.opal.utils.SimpleSelectionAdapter#handle(org.eclipse.swt.events.SelectionEvent)
			 */
			@Override
			public void handle(final SelectionEvent e) {
				DualList.this.moveSelectionToFirstPosition();
			}
		});
	}

	/**
	 * Creates the button select.
	 */
	private void createButtonSelect() {
		final Button buttonSelect = createButton(ARROW_RIGHT_IMAGE, false, GridData.CENTER);
		buttonSelect.addSelectionListener(new SimpleSelectionAdapter() {
			/**
			 * @see org.mihalis.opal.utils.SimpleSelectionAdapter#handle(org.eclipse.swt.events.SelectionEvent)
			 */
			@Override
			public void handle(final SelectionEvent e) {
				DualList.this.selectItem();
			}
		});
	}

	/**
	 * Creates the button move up.
	 */
	private void createButtonMoveUp() {
		final Button buttonMoveUp = createButton(ARROW_UP_IMAGE, false, GridData.CENTER);
		buttonMoveUp.addSelectionListener(new SimpleSelectionAdapter() {
			/**
			 * @see org.mihalis.opal.utils.SimpleSelectionAdapter#handle(org.eclipse.swt.events.SelectionEvent)
			 */
			@Override
			public void handle(final SelectionEvent e) {
				DualList.this.moveUpItem();
			}
		});
	}

	/**
	 * Creates the button deselect.
	 */
	private void createButtonDeselect() {
		final Button buttonDeselect = createButton(ARROW_LEFT_IMAGE, false, GridData.CENTER);
		buttonDeselect.addSelectionListener(new SimpleSelectionAdapter() {
			/**
			 * @see org.mihalis.opal.utils.SimpleSelectionAdapter#handle(org.eclipse.swt.events.SelectionEvent)
			 */
			@Override
			public void handle(final SelectionEvent e) {
				DualList.this.deselectItem();
			}
		});
	}

	/**
	 * Creates the button move down.
	 */
	private void createButtonMoveDown() {
		final Button buttonMoveDown = createButton(ARROW_DOWN_IMAGE, false, GridData.CENTER);
		buttonMoveDown.addSelectionListener(new SimpleSelectionAdapter() {
			/**
			 * @see org.mihalis.opal.utils.SimpleSelectionAdapter#handle(org.eclipse.swt.events.SelectionEvent)
			 */
			@Override
			public void handle(final SelectionEvent e) {
				DualList.this.moveDownItem();
			}
		});
	}

	/**
	 * Creates the button deselect all.
	 */
	private void createButtonDeselectAll() {
		final Button buttonDeselectAll = createButton(DOUBLE_LEFT_IMAGE, false, GridData.BEGINNING);
		buttonDeselectAll.addSelectionListener(new SimpleSelectionAdapter() {
			/**
			 * @see org.mihalis.opal.utils.SimpleSelectionAdapter#handle(org.eclipse.swt.events.SelectionEvent)
			 */
			@Override
			public void handle(final SelectionEvent e) {
				DualList.this.deselectAll();
			}
		});
	}

	/**
	 * Creates the button move last.
	 */
	private void createButtonMoveLast() {
		final Button buttonMoveLast = createButton(DOUBLE_DOWN_IMAGE, true, GridData.BEGINNING);
		buttonMoveLast.addSelectionListener(new SimpleSelectionAdapter() {
			/**
			 * @see org.mihalis.opal.utils.SimpleSelectionAdapter#handle(org.eclipse.swt.events.SelectionEvent)
			 */
			@Override
			public void handle(final SelectionEvent e) {
				DualList.this.moveSelectionToLastPosition();
			}
		});
	}

	/**
	 * Create a button.
	 *
	 * @param fileName file name of the icon
	 * @param verticalExpand if <code>true</code>, the button will take all the
	 *            available space vertically
	 * @param alignment button alignment
	 * @return a new button
	 */
	private Button createButton(final String fileName, final boolean verticalExpand, final int alignment) {
		final Button button = new Button(this, SWT.PUSH);
		final ClassLoader loader = org.mihalis.opal.itemSelector.DualList.class.getClassLoader();
		final Image image = new Image(getDisplay(), loader.getResourceAsStream("images/" + fileName));
		button.setImage(image);
		button.setLayoutData(new GridData(GridData.CENTER, alignment, false, verticalExpand));
		SWTGraphicUtil.addDisposer(button, image);
		return button;
	}

	/**
	 * Adds the argument to the end of the receiver's list.
	 *
	 * @param item the new item
	 * @see #add(DLItem,int)
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the item 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 DLItem item) {
		checkWidget();
		if (item == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}
		items.add(item);
		redrawTables();
	}

	/**
	 * Adds the argument to the receiver's list at the given zero-relative
	 * index.
	 * <p>
	 * Note: To add an item at the end of the list, use the result of calling
	 * <code>getItemCount()</code> as the index or use <code>add(DLItem)</code>.
	 * </p>
	 *
	 * @param item the new item
	 * @param index the index for the item
	 * @see #add(String)
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the item is null</li>
	 *                <li>ERROR_INVALID_RANGE - if the index is not between 0
	 *                and the number of elements in the list (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 DLItem item, final int index) {
		checkWidget();
		if (item == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}
		if (index < 0 || index >= items.size()) {
			SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		}
		items.add(index, item);
		redrawTables();
	}

	/**
	 * Adds the listener to the collection of listeners who will be notified
	 * when the user changes the receiver's selection, by sending it one of the
	 * messages defined in the <code>SelectionListener</code> interface.
	 *
	 * @param listener the listener which should be notified
	 * @see SelectionListener
	 * @see #removeSelectionListener
	 * @see SelectionEvent
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the listener 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 addSelectionListener(final SelectionListener listener) {
		checkWidget();
		if (listener == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}
		if (selectionListeners == null) {
			selectionListeners = new ArrayList<SelectionListener>();
		}
		selectionListeners.add(listener);
	}

	/**
	 * Removes the listener from the collection of listeners who will be
	 * notified when the user changes the receiver's selection.
	 *
	 * @param listener the listener which should no longer be notified
	 * @see SelectionListener
	 * @see #addSelectionListener
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the listener 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 removeSelectionListener(final SelectionListener listener) {
		checkWidget();
		if (listener == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}
		if (selectionListeners == null) {
			return;
		}
		selectionListeners.remove(listener);
	}

	/**
	 * Adds the listener to the collection of listeners who will be notified
	 * when the user changes the receiver's selection, by sending it one of the
	 * messages defined in the <code>SelectionChangeListener</code> interface.
	 *
	 * @param listener the listener which should be notified
	 * @see SelectionChangeListener
	 * @see #removeSelectionChangeListener
	 * @see SelectionChangeEvent
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the listener 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 addSelectionChangeListener(final SelectionChangeListener listener) {
		checkWidget();
		if (listener == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}
		if (selectionChangeListeners == null) {
			selectionChangeListeners = new ArrayList<SelectionChangeListener>();
		}
		selectionChangeListeners.add(listener);
	}

	/**
	 * Removes the listener from the collection of listeners who will be
	 * notified when the user changes the receiver's selection.
	 *
	 * @param listener the listener which should no longer be notified
	 * @see SelectionChangeListener
	 * @see #addSelectionChangeListener
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the listener 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 removeSelectionChangeListener(final SelectionChangeListener listener) {
		checkWidget();
		if (listener == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}
		if (selectionChangeListeners == null) {
			return;
		}
		selectionChangeListeners.remove(listener);
	}

	/**
	 * Deselects the item at the given zero-relative index in the receiver. 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 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 int index) {
		deselect(index, true);
	}

	/**
	 * Deselects the item at the given zero-relative index in the receiver. 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 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 deselectDoNotFireEvent(final int index) {
		deselect(index, false);
	}

	/**
	 * Deselects the item at the given zero-relative index in the receiver. 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
	 * @param shouldFireEvents the should fire events
	 * @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>
	 */
	private void deselect(final int index, final boolean shouldFireEvents) {
		checkWidget();
		if (index < 0 || index >= items.size()) {
			return;
		}
		final DLItem item = selection.remove(index);
		if (shouldFireEvents) {
			fireSelectionEvent(item);
		}

		final List<DLItem> deselectedItems = new ArrayList<DLItem>();
		item.setLastAction(LAST_ACTION.DESELECTION);
		deselectedItems.add(item);
		if (shouldFireEvents) {
			fireSelectionChangeEvent(deselectedItems);
		}
		redrawTables();
	}

	/**
	 * Deselects the items at the given zero-relative indices in the receiver.
	 * If the item at the given zero-relative index in the receiver is selected,
	 * it is deselected. If the item at the index was not selected, it remains
	 * deselected. Indices that are out of range and duplicate indices are
	 * ignored.
	 *
	 * @param indices the array of indices for the items to deselect
	 *
	 * @exception IllegalArgumentException
	 *                <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the set of indices 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 deselect(final int[] indices) {
		deselect(indices, true);
	}

	/**
	 * Deselects the items at the given zero-relative indices in the receiver.
	 * If the item at the given zero-relative index in the receiver is selected,
	 * it is deselected. If the item at the index was not selected, it remains
	 * deselected. Indices that are out of range and duplicate indices are
	 * ignored.
	 *
	 * @param indices the array of indices for the items to deselect
	 *
	 * @exception IllegalArgumentException
	 *                <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the set of indices 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 deselectDoNotFireEvent(final int[] indices) {
		deselect(indices, false);
	}

	/**
	 * Deselects the items at the given zero-relative indices in the receiver.
	 * If the item at the given zero-relative index in the receiver is selected,
	 * it is deselected. If the item at the index was not selected, it remains
	 * deselected. Indices that are out of range and duplicate indices are
	 * ignored.
	 *
	 * @param indices the array of indices for the items to deselect
	 * @param shouldFireEvents the should fire events
	 * @exception IllegalArgumentException <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the set of indices 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>
	 */
	private void deselect(final int[] indices, final boolean shouldFireEvents) {
		checkWidget();
		if (indices == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}

		final List<DLItem> toBeRemoved = new ArrayList<DLItem>();

		for (final int index : indices) {
			if (index < 0 || index >= items.size()) {
				continue;
			}
			toBeRemoved.add(selection.get(index));
		}

		for (final DLItem item : toBeRemoved) {
			selection.remove(item);
			if (shouldFireEvents) {
				fireSelectionEvent(item);
			}
		}
		if (shouldFireEvents) {
			fireSelectionChangeEvent(toBeRemoved);
		}

		toBeRemoved.clear();
		redrawTables();
	}

	/**
	 * Deselects the items at the given zero-relative indices in the receiver.
	 * If the item at the given zero-relative index in the receiver is selected,
	 * it is deselected. If the item at the index was not selected, it remains
	 * deselected. The range of the indices is inclusive. Indices that are out
	 * of range are ignored.
	 *
	 * @param start the start index of the items to deselect
	 * @param end the end index of the items to deselect
	 *
	 * @exception IllegalArgumentException
	 *                <ul>
	 *                <li>ERROR_INVALID_RANGE - if start is greater than end
	 *                </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 int start, final int end) {
		deselect(start, end, true);
	}

	/**
	 * Deselects the items at the given zero-relative indices in the receiver.
	 * If the item at the given zero-relative index in the receiver is selected,
	 * it is deselected. If the item at the index was not selected, it remains
	 * deselected. The range of the indices is inclusive. Indices that are out
	 * of range are ignored.
	 *
	 * @param start the start index of the items to deselect
	 * @param end the end index of the items to deselect
	 *
	 * @exception IllegalArgumentException
	 *                <ul>
	 *                <li>ERROR_INVALID_RANGE - if start is greater than end
	 *                </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 deselectDoNotFireEvent(final int start, final int end) {
		deselect(start, end, false);
	}

	/**
	 * Deselect.
	 *
	 * @param start the start
	 * @param end the end
	 * @param shouldFireEvents the should fire events
	 */
	private void deselect(final int start, final int end, final boolean shouldFireEvents) {
		checkWidget();
		if (start > end) {
			SWT.error(SWT.ERROR_INVALID_RANGE);
		}
		final List<DLItem> toBeRemoved = new ArrayList<DLItem>();

		for (int index = start; index <= end; index++) {
			if (index < 0 || index >= items.size()) {
				continue;
			}
			toBeRemoved.add(selection.get(index));
		}

		for (final DLItem item : toBeRemoved) {
			selection.remove(item);
			if (shouldFireEvents) {
				fireSelectionEvent(item);
			}
		}
		if (shouldFireEvents) {
			fireSelectionChangeEvent(toBeRemoved);
		}
		toBeRemoved.clear();
		redrawTables();
	}

	/**
	 * Deselects all selected items 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() {
		deselectAll(true);
	}

	/**
	 * Deselects all selected items 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 deselectAllDoNotFireEvent() {
		deselectAll(false);
	}

	/**
	 * Deselects all selected items in the receiver.
	 *
	 * @param shouldFireEvents the should fire events
	 * @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(final boolean shouldFireEvents) {
		checkWidget();
		items.addAll(selection);

		final List<DLItem> deselectedItems = new ArrayList<DLItem>();
		for (final DLItem item : selection) {
			item.setLastAction(LAST_ACTION.DESELECTION);
			deselectedItems.add(item);
			if (shouldFireEvents) {
				fireSelectionEvent(item);
			}
		}
		fireSelectionChangeEvent(deselectedItems);

		selection.clear();
		redrawTables();
	}

	/**
	 * Returns the item at the given, zero-relative index in the receiver.
	 * 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 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 DLItem getItem(final int index) {
		checkWidget();
		if (index < 0 || index >= items.size()) {
			SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		}
		return items.get(index);
	}

	/**
	 * Returns the number of items contained in the receiver.
	 *
	 * @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();
		return items.size();
	}

	/**
	 * Returns a (possibly empty) array of <code>DLItem</code>s which are the
	 * items in the receiver.
	 * <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 DLItem[] getItems() {
		checkWidget();
		return items.toArray(new DLItem[items.size()]);
	}

	/**
	 * Returns a (possibly empty) list of <code>DLItem</code>s which are the
	 * items in the receiver.
	 * <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<DLItem> getItemsAsList() {
		checkWidget();
		return new ArrayList<DLItem>(items);
	}

	/**
	 * Returns an array of <code>DLItem</code>s that are currently selected in
	 * the receiver. 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 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 DLItem[] getSelection() {
		checkWidget();
		return selection.toArray(new DLItem[items.size()]);
	}

	/**
	 * Returns a list of <code>DLItem</code>s that are currently selected in the
	 * receiver. 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 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<DLItem> getSelectionAsList() {
		checkWidget();
		return new ArrayList<DLItem>(selection);
	}

	/**
	 * Returns the number of selected items contained in the receiver.
	 *
	 * @return the number of selected 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 getSelectionCount() {
		checkWidget();
		return selection.size();
	}

	/**
	 * Removes the item from the receiver at the given zero-relative index.
	 *
	 * @param index the index for the item
	 *
	 * @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 remove(final int index) {
		checkWidget();
		if (index < 0 || index >= items.size()) {
			SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		}
		items.remove(index);
		redrawTables();
	}

	/**
	 * Removes the items from the receiver at the given zero-relative indices.
	 *
	 * @param indices the array of indices of the items
	 *
	 * @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>
	 *                <li>ERROR_NULL_ARGUMENT - if the indices array 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 int[] indices) {
		checkWidget();
		for (final int index : indices) {
			if (index < 0 || index >= items.size()) {
				SWT.error(SWT.ERROR_INVALID_ARGUMENT);
			}
			items.remove(index);
		}
		redrawTables();
	}

	/**
	 * Removes the items from the receiver which are between the given
	 * zero-relative start and end indices (inclusive).
	 *
	 * @param start the start of the range
	 * @param end the end of the range
	 *
	 * @exception IllegalArgumentException
	 *                <ul>
	 *                <li>ERROR_INVALID_RANGE - if either the start or end are
	 *                not between 0 and the number of elements in the list minus
	 *                1 (inclusive) or if start>end</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 int start, final int end) {
		checkWidget();
		if (start > end) {
			SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		}
		for (int index = start; index < end; index++) {
			if (index < 0 || index >= items.size()) {
				SWT.error(SWT.ERROR_INVALID_ARGUMENT);
			}
			items.remove(index);
		}
		redrawTables();
	}

	/**
	 * 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 item the item to remove
	 *
	 * @exception IllegalArgumentException
	 *                <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the item is null</li>
	 *                <li>ERROR_INVALID_ARGUMENT - if the item is not found in
	 *                the list</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 DLItem item) {
		checkWidget();
		if (item == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}
		if (!items.contains(item)) {
			SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		}
		items.remove(item);
		redrawTables();
	}

	/**
	 * Removes all of the items from the receiver.
	 * <p>
	 *
	 * @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();
		items.clear();
		redrawTables();
	}

	/**
	 * 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.
	 * Indices that are out of range are ignored.
	 *
	 * @param index the index of the item to select
	 *
	 * @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 int index) {
		select(index, true);
	}

	/**
	 * 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.
	 * Indices that are out of range are ignored.
	 *
	 * @param index the index of the item to select
	 *
	 * @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 selectDoNotFireEvent(final int index) {
		select(index, false);
	}

	/**
	 * Select.
	 *
	 * @param index the index
	 * @param shouldFireEvents the should fire events
	 */
	private void select(final int index, final boolean shouldFireEvents) {
		checkWidget();
		if (index < 0 || index >= items.size()) {
			return;
		}
		final List<DLItem> selectedItems = new ArrayList<DLItem>();
		final DLItem item = items.get(index);
		item.setLastAction(LAST_ACTION.SELECTION);
		selectedItems.add(item);
		selection.add(item);

		if (shouldFireEvents) {
			fireSelectionEvent(item);
			fireSelectionChangeEvent(selectedItems);
		}

		redrawTables();
	}

	/**
	 * Selects the items at the given zero-relative indices in the receiver. The
	 * current selection is not cleared before the new items are selected.
	 * <p>
	 * If the item at a given index is not selected, it is selected. If the item
	 * at a given index was already selected, it remains selected. Indices that
	 * are out of range and duplicate indices are ignored. If the receiver is
	 * single-select and multiple indices are specified, then all indices are
	 * ignored.
	 *
	 * @param indices the array of indices for the items to select
	 *
	 * @exception IllegalArgumentException
	 *                <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the array of indices 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 int[] indices) {
		select(indices, true);
	}

	/**
	 * Selects the items at the given zero-relative indices in the receiver. The
	 * current selection is not cleared before the new items are selected.
	 * <p>
	 * If the item at a given index is not selected, it is selected. If the item
	 * at a given index was already selected, it remains selected. Indices that
	 * are out of range and duplicate indices are ignored. If the receiver is
	 * single-select and multiple indices are specified, then all indices are
	 * ignored.
	 *
	 * @param indices the array of indices for the items to select
	 *
	 * @exception IllegalArgumentException
	 *                <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the array of indices 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 selectDoNotFireEvent(final int[] indices) {
		select(indices, false);
	}

	/**
	 * Select.
	 *
	 * @param indices the indices
	 * @param shouldFireEvents the should fire events
	 */
	private void select(final int[] indices, final boolean shouldFireEvents) {
		checkWidget();
		if (indices == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}

		final List<DLItem> selectedItems = new ArrayList<DLItem>();
		for (final int index : indices) {
			if (index < 0 || index >= items.size()) {
				continue;
			}
			final DLItem item = items.get(index);
			item.setLastAction(LAST_ACTION.SELECTION);
			selectedItems.add(item);

			selection.add(item);
			if (shouldFireEvents) {
				fireSelectionEvent(item);
			}
		}
		if (shouldFireEvents) {
			fireSelectionChangeEvent(selectedItems);
		}
		redrawTables();
	}

	/**
	 * Selects the items in the range specified by the given zero-relative
	 * indices in the receiver. The range of indices is inclusive. The current
	 * selection is not cleared before the new items are selected.
	 * <p>
	 * If an item in the given range is not selected, it is selected. If an item
	 * in the given range was already selected, it remains selected. Indices
	 * that are out of range are ignored and no items will be selected if start
	 * is greater than end. If the receiver is single-select and there is more
	 * than one item in the given range, then all indices are ignored.
	 *
	 * @param start the start of the range
	 * @param end the end of the range
	 * @see List#setSelection(int,int)
	 * @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 int start, final int end) {
		select(start, end, true);
	}

	/**
	 * Selects the items in the range specified by the given zero-relative
	 * indices in the receiver. The range of indices is inclusive. The current
	 * selection is not cleared before the new items are selected.
	 * <p>
	 * If an item in the given range is not selected, it is selected. If an item
	 * in the given range was already selected, it remains selected. Indices
	 * that are out of range are ignored and no items will be selected if start
	 * is greater than end. If the receiver is single-select and there is more
	 * than one item in the given range, then all indices are ignored.
	 *
	 * @param start the start of the range
	 * @param end the end of the range
	 * @see List#setSelection(int,int)
	 * @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 selectDoNotFireEvent(final int start, final int end) {
		select(start, end, false);
	}

	/**
	 * Select.
	 *
	 * @param start the start
	 * @param end the end
	 * @param shouldFireEvents the should fire events
	 */
	private void select(final int start, final int end, final boolean shouldFireEvents) {
		checkWidget();
		if (start > end) {
			SWT.error(SWT.ERROR_INVALID_RANGE);
		}
		final List<DLItem> selectedItems = new ArrayList<DLItem>();
		for (int index = start; index <= end; index++) {
			if (index < 0 || index >= items.size()) {
				continue;
			}
			final DLItem item = items.get(index);
			item.setLastAction(LAST_ACTION.SELECTION);
			selectedItems.add(item);
			selection.add(item);
			if (shouldFireEvents) {
				fireSelectionEvent(item);
			}
		}
		if (shouldFireEvents) {
			fireSelectionChangeEvent(selectedItems);
		}
		redrawTables();
	}

	/**
	 * Selects all of the items in the receiver.
	 * <p>
	 * If the receiver is single-select, do nothing.
	 *
	 * @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() {
		selectAll(true);
	}

	/**
	 * Selects all of the items in the receiver.
	 * <p>
	 * If the receiver is single-select, do nothing.
	 *
	 * @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 selectAllDoNotFireEvent() {
		selectAll(false);
	}

	/**
	 * Select all.
	 *
	 * @param shouldFireEvents the should fire events
	 */
	private void selectAll(final boolean shouldFireEvents) {
		checkWidget();
		selection.addAll(items);
		if (shouldFireEvents) {
			for (final DLItem item : items) {
				fireSelectionEvent(item);
			}
		}

		if (shouldFireEvents) {
			final List<DLItem> selectedItems = new ArrayList<DLItem>();
			for (final DLItem item : items) {
				item.setLastAction(LAST_ACTION.SELECTION);
				selectedItems.add(item);
			}
			fireSelectionChangeEvent(selectedItems);
		}
		items.clear();
		redrawTables();
	}

	/**
	 * Sets the bounds.
	 *
	 * @param x the x
	 * @param y the y
	 * @param width the width
	 * @param height the height
	 * @see org.eclipse.swt.widgets.Control#setBounds(int, int, int, int)
	 */
	@Override
	public void setBounds(final int x, final int y, final int width, final int height) {
		super.setBounds(x, y, width, height);
		final boolean itemsContainImage = itemsContainImage();
		final Point itemsTableDefaultSize = itemsTable.computeSize(SWT.DEFAULT, SWT.DEFAULT);
		final Point selectionTableDefaultSize = selectionTable.computeSize(SWT.DEFAULT, SWT.DEFAULT);

		int itemsTableSize = itemsTable.getSize().x;
		if (itemsTableDefaultSize.y > itemsTable.getSize().y) {
			itemsTableSize -= itemsTable.getVerticalBar().getSize().x;
		}

		int selectionTableSize = selectionTable.getSize().x;
		if (selectionTableDefaultSize.y > selectionTable.getSize().y) {
			selectionTableSize -= selectionTable.getVerticalBar().getSize().x;
		}

		if (itemsContainImage) {
			itemsTable.getColumn(0).pack();
			itemsTable.getColumn(1).setWidth(itemsTableSize - itemsTable.getColumn(0).getWidth());

			selectionTable.getColumn(0).pack();
			selectionTable.getColumn(1).setWidth(selectionTableSize - selectionTable.getColumn(0).getWidth());

		} else {
			itemsTable.getColumn(0).setWidth(itemsTableSize);
			selectionTable.getColumn(0).setWidth(selectionTableSize);
		}

		itemsTable.getColumn(0).pack();
		selectionTable.getColumn(0).pack();
	}

	/**
	 * Items contain image.
	 *
	 * @return <code>true</code> if any item contains an image
	 */
	private boolean itemsContainImage() {
		for (final DLItem item : items) {
			if (item.getImage() != null) {
				return true;
			}
		}

		for (final DLItem item : selection) {
			if (item.getImage() != null) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Sets the item in the receiver's list at the given zero-relative index to
	 * the item argument.
	 *
	 * @param index the index for the item
	 * @param item the new item
	 *
	 * @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>
	 *                <li>ERROR_NULL_ARGUMENT - if the item 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 setItem(final int index, final DLItem item) {
		checkWidget();
		if (item == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}
		if (index < 0 || index >= items.size()) {
			SWT.error(SWT.ERROR_INVALID_RANGE);
		}
		items.set(index, item);
		redrawTables();
	}

	/**
	 * Sets the receiver's items to be the given array of items.
	 *
	 * @param items the array of items
	 *
	 * @exception IllegalArgumentException
	 *                <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the items array is null</li>
	 *                <li>ERROR_INVALID_ARGUMENT - if an item in the items array
	 *                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 setItems(final DLItem[] items) {
		checkWidget();
		if (items == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}

		final List<DLItem> temp = new ArrayList<DLItem>();
		for (final DLItem item : items) {
			if (item == null) {
				SWT.error(SWT.ERROR_INVALID_ARGUMENT);
			}
			temp.add(item);
		}
		this.items.clear();
		this.items.addAll(temp);
		redrawTables();
	}

	/**
	 * Sets the receiver's items to be the given list of items.
	 *
	 * @param items the list of items
	 *
	 * @exception IllegalArgumentException
	 *                <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the items list is null</li>
	 *                <li>ERROR_INVALID_ARGUMENT - if an item in the items list
	 *                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 setItems(final List<DLItem> items) {
		checkWidget();
		checkWidget();
		if (items == null) {
			SWT.error(SWT.ERROR_NULL_ARGUMENT);
		}

		final List<DLItem> temp = new ArrayList<DLItem>();
		for (final DLItem item : items) {
			if (item == null) {
				SWT.error(SWT.ERROR_INVALID_ARGUMENT);
			}
			temp.add(item);
		}
		this.items.clear();
		this.items.addAll(temp);
		redrawTables();
	}

	/**
	 * Redraws all tables that compose this widget.
	 */
	private void redrawTables() {
		setRedraw(false);
		redrawTable(itemsTable, false);
		redrawTable(selectionTable, true);
		setRedraw(true);
		this.setBounds(getBounds());
	}

	/**
	 * Redraw a given table.
	 *
	 * @param table table to be redrawned
	 * @param isSelected if <code>true</code>, fill the table with the
	 *            selection. Otherwise, fill the table with the unselected
	 *            items.
	 */
	private void redrawTable(final Table table, final boolean isSelected) {
		clean(table);
		fillData(table, isSelected ? selection : items);
	}

	/**
	 * Cleans the content of a table.
	 *
	 * @param table table to be emptied
	 */
	private void clean(final Table table) {
		if (table == null) {
			return;
		}

		for (final TableItem item : table.getItems()) {
			item.dispose();
		}
	}

	/**
	 * Fill a table with data.
	 *
	 * @param table table to be filled
	 * @param listOfData list of data
	 */
	private void fillData(final Table table, final List<DLItem> listOfData) {
		final boolean itemsContainImage = itemsContainImage();
		for (final DLItem item : listOfData) {
			final TableItem tableItem = new TableItem(table, SWT.NONE);
			tableItem.setData(item);

			if (item.getBackground() != null) {
				tableItem.setBackground(item.getBackground());
			}

			if (item.getForeground() != null) {
				tableItem.setForeground(item.getForeground());
			}

			if (item.getImage() != null) {
				tableItem.setImage(0, item.getImage());
			}

			if (item.getFont() != null) {
				tableItem.setFont(item.getFont());
			}
			final int textColumn = itemsContainImage ? 1 : 0;
			tableItem.setText(textColumn, item.getText());
		}
	}

	/**
	 * Move the selected item to the first position.
	 */
	protected void moveSelectionToFirstPosition() {
		if (selectionTable.getSelectionCount() == 0) {
			return;
		}

		int index = 0;
		for (final TableItem tableItem : selectionTable.getSelection()) {
			final DLItem item = (DLItem) tableItem.getData();
			selection.remove(item);
			selection.add(index++, item);
		}

		redrawTables();
		selectionTable.select(0, index - 1);
		selectionTable.forceFocus();
	}

	/**
	 * Select a given item.
	 */
	protected void selectItem() {
		if (itemsTable.getSelectionCount() == 0) {
			return;
		}
		final List<DLItem> selectedItems = new ArrayList<DLItem>();
		for (final TableItem tableItem : itemsTable.getSelection()) {
			final DLItem item = (DLItem) tableItem.getData();
			item.setLastAction(LAST_ACTION.SELECTION);
			selectedItems.add(item);
			selection.add(item);
			items.remove(item);
			fireSelectionEvent(item);
		}
		fireSelectionChangeEvent(selectedItems);

		redrawTables();
	}

	/**
	 * Move the selected item up.
	 */
	protected void moveUpItem() {
		if (selectionTable.getSelectionCount() == 0) {
			return;
		}

		for (final int index : selectionTable.getSelectionIndices()) {
			if (index == 0) {
				selectionTable.forceFocus();
				return;
			}
		}

		final int[] newSelection = new int[selectionTable.getSelectionCount()];
		int newSelectionIndex = 0;
		for (final TableItem tableItem : selectionTable.getSelection()) {
			final int position = selection.indexOf(tableItem.getData());
			swap(position, position - 1);
			newSelection[newSelectionIndex++] = position - 1;
		}

		redrawTables();
		selectionTable.select(newSelection);
		selectionTable.forceFocus();
	}

	/**
	 * Deselect a given item.
	 */
	protected void deselectItem() {
		if (selectionTable.getSelectionCount() == 0) {
			return;
		}
		final List<DLItem> deselectedItems = new ArrayList<DLItem>();
		for (final TableItem tableItem : selectionTable.getSelection()) {
			final DLItem item = (DLItem) tableItem.getData();
			item.setLastAction(LAST_ACTION.DESELECTION);
			deselectedItems.add(item);
			items.add(item);
			selection.remove(item);
			fireSelectionEvent(item);
		}
		fireSelectionChangeEvent(deselectedItems);
		redrawTables();
	}

	/**
	 * Move the selected item down.
	 */
	protected void moveDownItem() {
		if (selectionTable.getSelectionCount() == 0) {
			return;
		}

		for (final int index : selectionTable.getSelectionIndices()) {
			if (index == selectionTable.getItemCount() - 1) {
				selectionTable.forceFocus();
				return;
			}
		}

		final int[] newSelection = new int[selectionTable.getSelectionCount()];
		int newSelectionIndex = 0;
		for (final TableItem tableItem : selectionTable.getSelection()) {
			final int position = selection.indexOf(tableItem.getData());
			swap(position, position + 1);
			newSelection[newSelectionIndex++] = position + 1;
		}

		redrawTables();
		selectionTable.select(newSelection);
		selectionTable.forceFocus();
	}

	/**
	 * Swap 2 items.
	 *
	 * @param first position of the first item to swap
	 * @param second position of the second item to swap
	 */
	private void swap(final int first, final int second) {
		final DLItem temp = selection.get(first);
		selection.set(first, selection.get(second));
		selection.set(second, temp);
	}

	/**
	 * Move the selected item to the last position.
	 */
	protected void moveSelectionToLastPosition() {
		if (selectionTable.getSelectionCount() == 0) {
			return;
		}

		final int numberOfSelectedElements = selectionTable.getSelectionCount();
		for (final TableItem tableItem : selectionTable.getSelection()) {
			final DLItem item = (DLItem) tableItem.getData();
			selection.remove(item);
			selection.add(item);
		}

		redrawTables();
		final int numberOfElements = selectionTable.getItemCount();
		selectionTable.select(numberOfElements - numberOfSelectedElements, numberOfElements - 1);
		selectionTable.forceFocus();
	}

	/**
	 * Call all selection listeners.
	 *
	 * @param item selected item
	 */
	private void fireSelectionEvent(final DLItem item) {
		if (selectionListeners == null) {
			return;
		}

		final Event event = new Event();
		event.button = 1;
		event.display = getDisplay();
		event.item = null;
		event.widget = this;
		event.data = item;
		final SelectionEvent selectionEvent = new SelectionEvent(event);

		for (final SelectionListener listener : selectionListeners) {
			listener.widgetSelected(selectionEvent);
		}
	}

	/**
	 * Fire selection change event.
	 *
	 * @param items the items
	 */
	private void fireSelectionChangeEvent(final List<DLItem> items) {
		if (selectionChangeListeners == null) {
			return;
		}

		final Event event = new Event();
		event.button = 1;
		event.display = getDisplay();
		event.item = null;
		event.widget = this;
		final SelectionChangeEvent selectionChangeEvent = new SelectionChangeEvent(event);
		selectionChangeEvent.setItems(items);

		for (final SelectionChangeListener listener : selectionChangeListeners) {
			listener.widgetSelected(selectionChangeEvent);
		}
	}
}
