blob: 94bfdbc6dfe6cff2ef881a57923577a3f2e5b8ff [file] [log] [blame]
/*******************************************************************************
* 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);
}
}
}