/*****************************************************************************
* Copyright (c) 2010 CEA LIST.
*
*
* 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:
* Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.editors;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.papyrus.infra.widgets.Activator;
import org.eclipse.papyrus.infra.widgets.messages.Messages;
import org.eclipse.papyrus.infra.widgets.providers.CollectionContentProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
/**
*
* This class provides an editor to select easily elements
* In the left side, we have the possible element to select and in the right side, we have the current selection
* Moreover, its possible to add a Button to provide some action. Often this button shall be used to create new element
*
*/
public class SelectionEditor extends Composite implements SelectionListener {
/** the initial selection */
protected final java.util.List<Object> initialSelection;
/** The object selector */
private IElementSelector selector;
/** The SWT Composite in which the selector is drawn */
protected Composite selectorSection;
/** The message section */
protected Composite messageSection;
/** The additional button section */
protected Composite createAdditionalButtonSection;
/** The up/down buttons section */
protected Composite rightButtonsSection;
/** The listViewer for chosen elements */
protected ListViewer selectedElementsViewer;
/** The list for chosen elements */
protected List selectedElements;
/** The add action button */
private Button add;
/** The remove action button */
private Button remove;
/** The add all action button */
private Button addAll;
/** The remove all action button */
private Button removeAll;
/** the up action button */
private Button up;
/** the down action button */
private Button down;
/** The label provider for the listViewer of chosen elements */
private ILabelProvider labelProvider;
/** The currently chosen elements */
protected final Collection<Object> currentSelection;
/** the listener for the additional button */
private SelectionListener additionalButtonSelectionListener;
/** the message for the editor */
private String message;
/*
* This dialog can provide a Button to do some optional action
*/
/** Indicates if the dialog provides a button */
private boolean withAdditionalButton = false;
/** the label of the button */
private String additionalButtonLabel = null;
/** the button */
private Button additionalButton;
/** The add/remove/addAll buttons section */
protected Composite buttonSection;
/**
*
* Constructor.
*
* @param parent
* the parent of this composite
* @param selector
* the selector
* @param labelProvider
* the label provider
* @param initialSelection
* the initial selection
*/
public SelectionEditor(Composite parent, IElementSelector selector, ILabelProvider labelProvider, java.util.List<Object> initialSelection) {
super(parent, SWT.NONE);
this.selector = selector;
this.labelProvider = labelProvider;
this.initialSelection = new ArrayList<Object>();
for(Object current : initialSelection) {
this.initialSelection.add(current);
}
currentSelection = initialSelection;
}
/**
* This methods create this editor
*/
public void create() {
Composite parent = this;
GridLayout layout = new GridLayout(1, true);
GridData data = new GridData();
data.grabExcessHorizontalSpace = true;
data.grabExcessVerticalSpace = true;
parent.setLayout(layout);
createMessageSection(parent);
createBody(parent);
createCreateButtonSection(parent);
}
/**
* This method create the body of the editor :
* <ul>
* <li>the selector</li>
* <li>the list</li>
* <li>the buttons Add, AddAll, Remove, RemoveAll, Up, Down</li>
* </ul>
*
* @param parent
* the parent composite
*/
protected void createBody(Composite parent) {
Composite par = new Composite(parent, SWT.NONE);
createSelectorSection(par);
createControlsSection(par);
createListSection(par);
createRightButtonsSection(par);
GridLayout layout = new GridLayout();
layout.makeColumnsEqualWidth = false;
layout.numColumns = 4;
par.setLayout(layout);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
par.setLayoutData(data);
}
/**
* Creates the Message section
*
* @param parent
* the parent of the {@link Composite}
*/
protected void createMessageSection(Composite parent) {
messageSection = new Composite(parent, SWT.NONE);
Label label = new Label(messageSection, SWT.NONE);
label.setText(message);
messageSection.setLayout(new FillLayout(SWT.HORIZONTAL));
}
/**
* Creates the button section
*
* @param parent
* the parent of the {@link Composite}
*/
protected void createCreateButtonSection(Composite parent) {
if(this.withAdditionalButton) {
buttonSection = new Composite(parent, SWT.NONE);
additionalButton = new Button(buttonSection, SWT.PUSH);
if(additionalButtonLabel != null) {
additionalButton.setText(additionalButtonLabel);
}
buttonSection.setLayout(new FillLayout());
this.additionalButton.addSelectionListener(additionalButtonSelectionListener);
}
}
/**
* Creates the selector section
*
* @param parent
* The composite in which the section is created
*/
protected void createSelectorSection(Composite parent) {
selectorSection = new Composite(parent, SWT.NONE);
selectorSection.setLayout(new FillLayout());
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
data.widthHint = 400;
// data.exclude = true;
selectorSection.setLayoutData(data);
selector.createControls(selectorSection);
}
/**
* Creates the main controls section (Add, remove, Add all, remove all)
*
* @param parent
* The composite in which the section is created
*/
protected void createControlsSection(Composite parent) {
buttonSection = new Composite(parent, SWT.NONE);
buttonSection.setLayout(new GridLayout(1, true));
add = new Button(buttonSection, SWT.PUSH);
add.setImage(Activator.getDefault().getImage("/icons/arrow_right.gif")); //$NON-NLS-1$
add.addSelectionListener(this);
add.setToolTipText(Messages.MultipleValueSelectorDialog_AddSelectedElements);
remove = new Button(buttonSection, SWT.PUSH);
remove.setImage(Activator.getDefault().getImage("/icons/arrow_left.gif")); //$NON-NLS-1$
remove.addSelectionListener(this);
remove.setToolTipText(Messages.MultipleValueEditor_RemoveSelectedElements);
addAll = new Button(buttonSection, SWT.PUSH);
addAll.setImage(Activator.getDefault().getImage("/icons/arrow_double.gif")); //$NON-NLS-1$
addAll.addSelectionListener(this);
addAll.setToolTipText(Messages.MultipleValueSelectorDialog_AddAllElements);
removeAll = new Button(buttonSection, SWT.PUSH);
removeAll.setImage(Activator.getDefault().getImage("/icons/arrow_left_double.gif")); //$NON-NLS-1$
removeAll.addSelectionListener(this);
removeAll.setToolTipText(Messages.MultipleValueSelectorDialog_RemoveAllElements);
}
/**
* Creates the list displaying the currently selected elements
*
* @param parent
* The composite in which the section is created
*/
protected void createListSection(Composite parent) {
Composite listSection = new Composite(parent, SWT.NONE);
selectedElements = new List(listSection, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
data.widthHint = 400;
listSection.setLayout(new FillLayout());
listSection.setLayoutData(data);
selectedElementsViewer = new ListViewer(selectedElements);
selectedElementsViewer.setContentProvider(CollectionContentProvider.instance);
if(labelProvider != null)
selectedElementsViewer.setLabelProvider(labelProvider);
selectedElementsViewer.setInput(currentSelection);
selector.setSelectedElements(currentSelection.toArray());
}
/**
* Creates the up/down controls section
*
* @param parent
* The composite in which the section is created
*/
protected void createRightButtonsSection(Composite parent) {
rightButtonsSection = new Composite(parent, SWT.NONE);
rightButtonsSection.setLayout(new GridLayout(1, true));
up = new Button(rightButtonsSection, SWT.PUSH);
up.setImage(Activator.getDefault().getImage("/icons/Up_12x12.gif")); //$NON-NLS-1$
up.addSelectionListener(this);
up.setToolTipText(Messages.MultipleValueEditor_MoveSelectedElementsUp);
down = new Button(rightButtonsSection, SWT.PUSH);
down.setImage(Activator.getDefault().getImage("/icons/Down_12x12.gif")); //$NON-NLS-1$
down.addSelectionListener(this);
down.setToolTipText(Messages.MultipleValueEditor_MoveSelectedElementsDown);
}
/**
* {@inheritDoc} Handles the events on one of the control buttons
*
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*
* @param e
* The event that occurred
*/
public void widgetSelected(SelectionEvent e) {
if(e.widget == add) {
addAction();
} else if(e.widget == remove) {
removeAction();
} else if(e.widget == addAll) {
addAllAction();
} else if(e.widget == removeAll) {
removeAllAction();
} else if(e.widget == up) {
upAction();
} else if(e.widget == down) {
downAction();
}
}
/**
* Handles the "Add" action
*/
protected void addAction() {
Object[] elements = selector.getSelectedElements();
addElements(elements);
}
/**
* Handles the "Up" action
*/
protected void upAction() {
IStructuredSelection selection = (IStructuredSelection)selectedElementsViewer.getSelection();
//We need a list to move objects. LinkedHashSet can't do that
java.util.List<Object> list = new LinkedList<Object>(currentSelection);
for(Object o : selection.toArray()) {
int oldIndex = list.indexOf(o);
if(oldIndex > 0)
move(list, oldIndex, oldIndex - 1);
}
currentSelection.clear();
currentSelection.addAll(list);
IStructuredSelection selectionCopy = new StructuredSelection(selection.toArray());
selectedElementsViewer.setSelection(selectionCopy);
selectedElementsViewer.refresh();
}
/**
* Handles the "Down" action
*/
protected void downAction() {
IStructuredSelection selection = (IStructuredSelection)selectedElementsViewer.getSelection();
//We need a list to move objects. LinkedHashSet can't do that
java.util.List<Object> list = new LinkedList<Object>(currentSelection);
int maxIndex = list.size() - 1;
Object[] selectionArray = selection.toArray();
for(int i = selectionArray.length - 1; i >= 0; i--) {
Object o = selectionArray[i];
int oldIndex = list.indexOf(o);
if(oldIndex < maxIndex)
move(list, oldIndex, oldIndex + 1);
}
currentSelection.clear();
currentSelection.addAll(list);
IStructuredSelection selectionCopy = new StructuredSelection(selection.toArray());
selectedElementsViewer.setSelection(selectionCopy);
selectedElementsViewer.refresh();
}
/**
* Moves an element from oldIndex to newIndex
*
* @param list
* The list in which to move the object
* @param oldIndex
* @param newIndex
*/
protected void move(java.util.List<Object> list, int oldIndex, int newIndex) {
int size = list.size();
if(oldIndex < 0 || oldIndex >= size)
throw new IndexOutOfBoundsException("oldIndex: " + oldIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$
if(newIndex < 0 || newIndex >= size)
throw new IndexOutOfBoundsException("newIndex: " + newIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$
Object element = list.remove(oldIndex);
list.add(newIndex, element);
}
/**
* Handles the "Remove" action
*/
protected void removeAction() {
IStructuredSelection selection = (IStructuredSelection)selectedElementsViewer.getSelection();
if(selection.isEmpty())
return;
for(Object element : selection.toArray()) {
currentSelection.remove(element);
}
selector.setSelectedElements(currentSelection.toArray());
selectedElementsViewer.setSelection(null);
selectedElementsViewer.refresh();
}
/**
* Handles the "Remove all" action
*/
protected void removeAllAction() {
currentSelection.clear();
selector.setSelectedElements(new Object[0]);
selectedElementsViewer.setSelection(null);
selectedElementsViewer.refresh();
}
/**
* Handles the "Add All" action
*/
protected void addAllAction() {
Object[] elements = selector.getAllElements();
addElements(elements);
}
/**
* Adds the specified elements to the currently selected elements (For
* "Add" and "Add all" actions)
*
* @param elements
* The elements to be added
*/
protected void addElements(Object[] elements) {
if(elements != null) {
currentSelection.addAll(Arrays.asList(elements));
selectedElementsViewer.refresh();
}
}
/**
*
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*
* @param e
*/
public void widgetDefaultSelected(SelectionEvent e) {
//Nothing to do
}
public void setAdditionalButton(boolean withAdditionalButton, String messageButton, SelectionListener listener) {
this.withAdditionalButton = withAdditionalButton;
this.additionalButtonLabel = messageButton;
this.additionalButtonSelectionListener = listener;
}
/**
* Set the message displayed by the Editor
*
* @param string
* the message displayed by the editor
*/
public void setMessage(String string) {
this.message = string;
}
/**
* Returns all selected elements
*
* @return
* all selected elements
*/
public Collection<?> getSelectedElements() {
return currentSelection;
}
/**
* Returns the list of the elements to remove
*
* @return
* the list of the elements to remove
*/
public java.util.List<Object> getElementToRemove() {
java.util.List<Object> removedObject = new ArrayList<Object>();
for(Object current : this.initialSelection) {
if(!getSelectedElements().contains(current)) {
removedObject.add(current);
}
}
return removedObject;
}
/**
* Returns the list of the elements to add
*
* @return
* the list of the elements to add
*/
public java.util.List<Object> getElementToAdd() {
java.util.List<Object> addedObject = new ArrayList<Object>();
for(Object current : getSelectedElements()) {
if(!this.initialSelection.contains(current)) {
addedObject.add(current);
}
}
return addedObject;
}
}