/*******************************************************************************
* Copyright (c) 2008, 2011 CEA LIST and others.
* 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:
* Patrick Tessier (CEA LIST) Patrick.tessier@cea.fr - Initial API and implementation
* Obeo - Some improvements
*******************************************************************************/
package org.eclipse.emf.eef.runtime.ui.widgets;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.emf.eef.runtime.EEFRuntimePlugin;
import org.eclipse.emf.eef.runtime.ui.utils.EEFRuntimeUIMessages;
import org.eclipse.emf.eef.runtime.ui.utils.EditingUtils;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertyConstants;
/**
* Base class for a complex section composite. This composite has a label, a table that describes a tree
* structure, and four buttons on the side of the table to add an element into the table, remove selected
* element(s), move up or down the selected element.
*
* @author Remi SCHNEKENBURGER
* @author Patrick Tessier
* @author <a href="mailto:jerome.benois@obeo.fr">Jerome Benois</a>
* @author <a href="mailto:goulwen.lefur@obeo.fr">Goulwen Le Fur</a>
* @author <a href="mailto:stephane.bouchet@obeo.fr">Stephane Bouchet</a>
*/
public class ReferencesTable implements IPropertiesFilteredWidget {
/**
* Image for the add element button.
*/
final protected static Image NEW_ELEMENT_IMG = EEFRuntimePlugin.getImage(EEFRuntimePlugin.ICONS_16x16
+ "Add_16x16.gif"); //$NON-NLS-1$
/**
* Image for the delete element button.
*/
final protected static Image DELETE_ELEMENT_IMG = EEFRuntimePlugin.getImage(EEFRuntimePlugin.ICONS_16x16
+ "Delete_16x16.gif"); //$NON-NLS-1$
/**
* Image for the up button.
*/
final protected static Image UP_ELEMENT_IMG = EEFRuntimePlugin.getImage(EEFRuntimePlugin.ICONS_16x16
+ "ArrowUp_16x16.gif"); //$NON-NLS-1$
/**
* Image for the down button.
*/
final protected static Image DOWN_ELEMENT_IMG = EEFRuntimePlugin.getImage(EEFRuntimePlugin.ICONS_16x16
+ "ArrowDown_16x16.gif"); //$NON-NLS-1$
/** list of element that we want to display * */
private Object input;
/**
* Label above the table.
*/
private Label label;
/**
* Table that displays a property for the current element.
*/
private Table table;
/** the table viewer to associate the label provider * */
private TableViewer tableViewer;
/**
* Button that adds an element.
*/
protected Button addButton;
/**
* Button that removes an element.
*/
protected Button removeButton;
/**
* button that moves the element up.
*/
protected Button upButton;
/**
* button that moves the element down.
*/
protected Button downButton;
/**
* Listener for the add button.
*/
private MouseListener addButtonlistener;
/**
* Listener for the delete button.
*/
private MouseListener removeButtonlistener;
/**
* Listener for the up button.
*/
private MouseListener upButtonlistener;
/**
* Listener for the down button.
*/
private MouseListener downButtonlistener;
private Listener tableListener;
private int upperBound = -1;
private int lowerBound = 0;
/**
* The listener used by the client to handle business events (Add, Remove, Move, NavigateTo)
*/
private ReferencesTableListener referencesTableListener;
private String labelToDisplay;
/**
* The Form tool kit use to use this widget in an Eclipse Forms compliant mode
*/
private FormToolkit widgetFactory;
/**
* The main composite
*/
private Composite composite;
/**
* The adapter factory.
*/
protected AdapterFactory adapterFactory = new ComposedAdapterFactory(
ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
/**
* The help text
*/
private String helpText;
/** The business rules filters. */
protected List<ViewerFilter> bpFilters;
/** The filters. */
protected List<ViewerFilter> filters;
/**
* ContentProvider of the table
*/
private IStructuredContentProvider contentProvider;
/**
* the constructor
*
* @param labeltoDisplay
* the label to display
* @param the
* listener to handle Add, Remove, Move and NavigateTo events
*/
public ReferencesTable(String labeltoDisplay, ReferencesTableListener referenceListener) {
this.labelToDisplay = labeltoDisplay;
this.addButtonlistener = new AddButtonlistener();
this.removeButtonlistener = new RemoveButtonlistener();
this.upButtonlistener = new UpButtonlistener();
this.downButtonlistener = new DownButtonlistener();
bpFilters = new ArrayList<ViewerFilter>();
filters = new ArrayList<ViewerFilter>();
addTableReferenceListener(referenceListener);
}
public void addTableReferenceListener(ReferencesTableListener referenceListener) {
this.referencesTableListener = referenceListener;
}
public void addSelectionListener(SelectionListener selectionListener) {
this.table.addSelectionListener(selectionListener);
}
public void createControls(Composite parent, FormToolkit widgetFactory) {
this.widgetFactory = widgetFactory;
createControls(parent);
}
private Composite createComposite(Composite parent) {
Composite composite;
if (widgetFactory == null) {
composite = new Composite(parent, SWT.NONE);
} else {
composite = widgetFactory.createComposite(parent);
}
return composite;
}
private Button createButton(Composite parent, String text, int style) {
Button button;
if (widgetFactory == null) {
button = new Button(parent, style);
button.setText(text);
} else {
button = widgetFactory.createButton(parent, text, style);
}
return button;
}
private Label createLabel(Composite parent, String text, int style) {
Label label;
if (widgetFactory == null) {
label = new Label(parent, SWT.PUSH);
label.setText(text);
} else {
label = widgetFactory.createLabel(parent, text, style);
}
return label;
}
private Table createTable(Composite parent, int style) {
Table table;
if (widgetFactory == null) {
table = new Table(parent, style);
} else {
table = widgetFactory.createTable(parent, style);
}
return table;
}
public void createControls(Composite parent) {
composite = createComposite(parent);
if (parent instanceof ExpandableComposite) {
((ExpandableComposite)parent).setClient(composite);
}
FormLayout formLayout = new FormLayout();
formLayout.marginTop = 7;
composite.setLayout(formLayout);
FormData data;
// Create Help Button
data = new FormData();
data.top = new FormAttachment(-2, 0);
data.right = new FormAttachment(100, -ITabbedPropertyConstants.HSPACE);
Control helpButton = null;
if (helpText != null) {
if (widgetFactory != null) {
helpButton = FormUtils.createHelpButton(widgetFactory, composite, helpText, null);
} else {
helpButton = SWTUtils.createHelpButton(composite, helpText, null);
}
helpButton.setLayoutData(data);
}
// ///////////////////////////////////////////////////////////////////////////
// Create and place button vertically on the left side
// Button : Add Element
// Button Delete Element
removeButton = createButton(composite, "", SWT.PUSH); //$NON-NLS-1$
removeButton.setVisible(true);
removeButton.setImage(DELETE_ELEMENT_IMG);
removeButton.setToolTipText(EEFRuntimeUIMessages.ReferencesTable_remove_tooltip);
data = new FormData();
// data.top = new FormAttachment(addButton,
// ITabbedPropertyConstants.HSPACE);
data.top = new FormAttachment(-6, 0);
if (helpText != null) {
data.right = new FormAttachment(helpButton, -ITabbedPropertyConstants.HSPACE);
} else {
data.right = new FormAttachment(100, -ITabbedPropertyConstants.HSPACE);
}
removeButton.setLayoutData(data);
removeButton.addMouseListener(removeButtonlistener);
addButton = createButton(composite, "", SWT.PUSH); //$NON-NLS-1$
addButton.setVisible(true);
addButton.setImage(NEW_ELEMENT_IMG);
addButton.setToolTipText(EEFRuntimeUIMessages.ReferencesTable_add_tooltip);
data = new FormData();
// data.top = new FormAttachment(label,
// ITabbedPropertyConstants.HSPACE);
data.top = new FormAttachment(-6, 0);
data.right = new FormAttachment(removeButton, -ITabbedPropertyConstants.HSPACE);
addButton.setLayoutData(data);
addButton.addMouseListener(addButtonlistener);
// Button Up
upButton = createButton(composite, "", SWT.PUSH); //$NON-NLS-1$
upButton.setVisible(true);
upButton.setImage(UP_ELEMENT_IMG);
upButton.setToolTipText(EEFRuntimeUIMessages.ReferencesTable_up_tooltip);
data = new FormData();
// data.top = new FormAttachment(removeButton,
// ITabbedPropertyConstants.HSPACE);
data.top = new FormAttachment(-6, 0);
data.right = new FormAttachment(addButton, -ITabbedPropertyConstants.HSPACE);
upButton.setLayoutData(data);
upButton.addMouseListener(upButtonlistener);
// Button Down
downButton = createButton(composite, "", SWT.PUSH); //$NON-NLS-1$
downButton.setVisible(true);
downButton.setImage(DOWN_ELEMENT_IMG);
downButton.setToolTipText(EEFRuntimeUIMessages.ReferencesTable_down_tooltip);
data = new FormData();
// data.top = new FormAttachment(upButton,
// ITabbedPropertyConstants.HSPACE);
data.top = new FormAttachment(-6, 0);
data.right = new FormAttachment(upButton, -ITabbedPropertyConstants.HSPACE);
downButton.setLayoutData(data);
downButton.addMouseListener(downButtonlistener);
// Create label
label = createLabel(composite, labelToDisplay, SWT.NONE);
// label.setLayout(new FormLayout());
data = new FormData();
data.left = new FormAttachment(2, 0);
data.right = new FormAttachment(downButton, -ITabbedPropertyConstants.HSPACE - 5/* 50 */);
data.top = new FormAttachment(0, 0);
label.setLayoutData(data);
// ///////////////////////////////////////////////////////////////////////////
// Create and place Table
table = createTable(composite, SWT.MULTI | SWT.H_SCROLL | SWT.BORDER);
table.setLayout(new FormLayout());
table.setVisible(true);
table.addListener(SWT.MouseDoubleClick, tableListener = new EditItemListener());
// createTable
tableViewer = new TableViewer(table);
// The filters.
data = new FormData();
data.height = 100;
data.top = new FormAttachment(label, ITabbedPropertyConstants.VSPACE + 4);
data.left = new FormAttachment(0, ITabbedPropertyConstants.HSPACE);
data.right = new FormAttachment(100, -ITabbedPropertyConstants.HSPACE);
table.setLayoutData(data);
table.addMouseListener(new MouseListener() {
public void mouseDoubleClick(MouseEvent e) {
if (table.getSelection() != null && table.getSelectionCount() != 0
&& table.getSelection()[0].getData() instanceof EObject) {
// Navigate
referencesTableListener.navigateTo((EObject)table.getSelection()[0].getData());
}
}
public void mouseDown(MouseEvent e) {
}
public void mouseUp(MouseEvent e) {
}
});
// tableViewer.refresh();
// table.pack();
}
/**
* @param layoutData
* the layoutData to set
*/
public void setLayoutData(Object layoutData) {
composite.setLayoutData(layoutData);
}
/**
* @param contentProvider
* contentProvider to use in the Table
*/
public void setContentProvider(IStructuredContentProvider contentProvider) {
this.contentProvider = contentProvider;
}
public void setUpperBound(int value) {
if (value < 0)
this.upperBound = -1;
else
this.upperBound = value;
}
public int getUpperBound() {
return this.upperBound;
}
public void setLowerBound(int value) {
if (value <= 0)
this.lowerBound = 0;
else
this.lowerBound = value;
}
public int getLowerBound() {
return this.lowerBound;
}
private int getSize() {
if (contentProvider != null && input != null)
return contentProvider.getElements(input).length;
return -1;
}
private int indexOf(Object elem) {
Object[] elements = contentProvider.getElements(input);
for (int i = 0; i < elements.length; i++) {
Object next = elements[i];
if (next.equals(elem))
return i;
}
return -1;
}
/**
* Sets the given ID to the EMFComboViewer
*
* @param id
* the ID to give
*/
public void setID(Object id) {
EditingUtils.setID(table, id);
EditingUtils.setID(addButton, id);
EditingUtils.setID(removeButton, id);
EditingUtils.setID(upButton, id);
EditingUtils.setID(downButton, id);
}
/**
* Defines the type of reference table
*
* @param id
* the type to give
*/
public void setEEFType(String type) {
EditingUtils.setEEFtype(table, type + "::field");
EditingUtils.setEEFtype(addButton, type + "::addbutton");
EditingUtils.setEEFtype(removeButton, type + "::removebutton");
EditingUtils.setEEFtype(upButton, type + "::upbutton");
EditingUtils.setEEFtype(downButton, type + "::downbutton");
}
/**
* @return the ID of the EObjectFlatComboViewer
*/
public Object getID() {
return EditingUtils.getID(table);
}
/**
* @param helpText
*/
public void setHelpText(String helpText) {
this.helpText = helpText;
}
public void refresh() {
tableViewer.refresh();
computeAddButtonStatus();
computeRemoveButtonStatus();
}
private void computeRemoveButtonStatus() {
if (getTable().getEnabled() && (getSize() > this.lowerBound))
removeButton.setEnabled(true);
else
removeButton.setEnabled(false);
}
private void computeAddButtonStatus() {
if (getTable().getEnabled() && (this.upperBound < 0 || getSize() < this.upperBound))
addButton.setEnabled(true);
else
addButton.setEnabled(false);
}
/**
* display the content of the table
*/
public void initLabelProvider() {
if (!table.isDisposed()) {
// set the label provider
tableViewer.setLabelProvider(getLabelProvider());
}
}
/**
* Returns the label provider for the composite
*
* @return the label provider or <code>null</code>
*/
public AdapterFactoryLabelProvider getLabelProvider() {
return new AdapterFactoryLabelProvider(adapterFactory);
}
/**
* Disable Move capability (Hide Up and Down buttons)
*/
public void disableMove() {
upButton.setVisible(false);
downButton.setVisible(false);
}
/**
* Listener for the Add Button Specific behavior is implemented in
* {@link ReferencesTable#addButtonPressed()}.
*
* @author Remi SCHNEKENBURGER
*/
private class AddButtonlistener implements MouseListener {
/**
* {@inheritDoc}
*/
public void mouseDoubleClick(MouseEvent e) {
// do nothing
}
/**
* {@inheritDoc}
*/
public void mouseDown(MouseEvent e) {
// do nothing
}
/**
* {@inheritDoc}
*/
public void mouseUp(MouseEvent e) {
referencesTableListener.handleAdd();
}
}
/**
* Listener for the Remove Button Specific behavior is implemented in
* {@link ReferencesTable#removeButtonPressed()}.
*
* @author Remi SCHNEKENBURGER
*/
private class RemoveButtonlistener implements MouseListener {
/**
* {@inheritDoc}
*/
public void mouseDoubleClick(MouseEvent e) {
// do nothing
}
/**
* {@inheritDoc}
*/
public void mouseDown(MouseEvent e) {
// do nothing
}
/**
* {@inheritDoc}
*/
public void mouseUp(MouseEvent e) {
// Keep selection
TableItem[] tableItems = table.getSelection();
for (int i = (tableItems.length - 1); i >= 0; i--) {
// Remove
referencesTableListener.handleRemove((EObject)tableItems[i].getData());
}
}
}
/**
* Listener for the Up Button Specific behavior is implemented in
* {@link ReferencesTable#upButtonPressed()}.
*
* @author Remi SCHNEKENBURGER
*/
private class UpButtonlistener implements MouseListener {
/**
* {@inheritDoc}
*/
public void mouseDoubleClick(MouseEvent e) {
// do nothing
}
/**
* {@inheritDoc}
*/
public void mouseDown(MouseEvent e) {
// do nothing
}
/**
* {@inheritDoc}
*/
public void mouseUp(MouseEvent e) {
// Keep selection
TableItem[] tableItems = table.getSelection();
for (int i = (tableItems.length - 1); i >= 0; i--) {
// Get use case
int newIndex = indexOf(tableItems[i].getData()) - 1;
if (newIndex >= 0 && newIndex < getSize()) {
// Move
referencesTableListener.handleMove((EObject)tableItems[i].getData(), newIndex + 1,
newIndex);
}
}
}
}
/**
* Listener for the Down Button Specific behavior is implemented in
* {@link ReferencesTable#downButtonPressed()}.
*
* @author Remi SCHNEKENBURGER
*/
private class DownButtonlistener implements MouseListener {
/**
* {@inheritDoc}
*/
public void mouseDoubleClick(MouseEvent e) {
// do nothing
}
/**
* {@inheritDoc}
*/
public void mouseDown(MouseEvent e) {
// do nothing
}
/**
* {@inheritDoc}
*/
public void mouseUp(MouseEvent e) {
TableItem[] tableItems = table.getSelection();
for (int i = (tableItems.length - 1); i >= 0; i--) {
// Get use case
int newIndex = indexOf(tableItems[i].getData()) + 1;
if (newIndex >= 0 && newIndex < getSize()) {
// Move
referencesTableListener.handleMove((EObject)tableItems[i].getData(), newIndex - 1,
newIndex);
}
}
}
}
/**
*
*/
private class EditItemListener implements Listener {
/**
* @{inheritDoc}
*/
public void handleEvent(Event event) {
if (table.getSelection().length > 0) {
TableItem item = table.getSelection()[0];
if (item.getData() instanceof EObject) {
// Edit
referencesTableListener.handleEdit((EObject)item.getData());
}
}
}
}
/**
* removes listeners from buttons.
*/
public void dispose() {
if (addButton != null && !addButton.isDisposed())
addButton.removeMouseListener(addButtonlistener);
if (removeButton != null && !removeButton.isDisposed())
removeButton.removeMouseListener(removeButtonlistener);
if (upButton != null && !upButton.isDisposed())
upButton.removeMouseListener(upButtonlistener);
if (downButton != null && !downButton.isDisposed())
downButton.removeMouseListener(downButtonlistener);
if (table != null && !table.isDisposed())
table.removeListener(SWT.MouseDoubleClick, tableListener);
if (filters != null) {
filters.clear();
filters = null;
}
if (bpFilters != null) {
bpFilters.clear();
bpFilters = null;
}
}
/**
* input of viewer
*
* @param input
*/
public void setInput(Object input) {
this.input = input;
initLabelProvider();
tableViewer.setContentProvider(contentProvider);
tableViewer.setInput(input);
for (ViewerFilter filter : filters) {
this.tableViewer.addFilter(filter);
}
for (ViewerFilter filter : bpFilters) {
this.tableViewer.addFilter(filter);
}
computeAddButtonStatus();
computeRemoveButtonStatus();
}
/**
* @return the input of the viewer
*/
public Object getInput() {
return input;
}
public interface ReferencesTableListener {
void handleAdd();
void handleRemove(EObject element);
void handleMove(EObject element, int oldIndex, int newIndex);
void handleEdit(EObject element);
void navigateTo(EObject element);
}
/*
* (non-Javadoc)
* @seeorg.eclipse.emf.eef.runtime.ui.widgets.IPropertiesFilteredWidget#
* addBusinessRuleFilter(org.eclipse. jface.viewers.ViewerFilter)
*/
public void addBusinessRuleFilter(ViewerFilter filter) {
this.bpFilters.add(filter);
if (this.tableViewer != null) {
this.tableViewer.addFilter(filter);
this.tableViewer.refresh();
}
}
/*
* (non-Javadoc)
* @see org.eclipse.emf.eef.runtime.ui.widgets.IPropertiesFilteredWidget#addFilter
* (org.eclipse.jface.viewers .ViewerFilter)
*/
public void addFilter(ViewerFilter filter) {
this.filters.add(filter);
if (this.tableViewer != null) {
this.tableViewer.addFilter(filter);
this.tableViewer.refresh();
}
}
/*
* (non-Javadoc)
* @seeorg.eclipse.emf.eef.runtime.ui.widgets.IPropertiesFilteredWidget#
* removeBusinessRuleFilter(org.eclipse .jface.viewers.ViewerFilter)
*/
public void removeBusinessRuleFilter(ViewerFilter filter) {
this.bpFilters.remove(filter);
if (this.tableViewer != null) {
this.tableViewer.removeFilter(filter);
this.tableViewer.refresh();
}
}
/*
* (non-Javadoc)
* @see org.eclipse.emf.eef.runtime.ui.widgets.IPropertiesFilteredWidget#removeFilter
* (org.eclipse.jface.viewers .ViewerFilter)
*/
public void removeFilter(ViewerFilter filter) {
this.filters.remove(filter);
if (this.tableViewer != null) {
this.tableViewer.removeFilter(filter);
this.tableViewer.refresh();
}
}
protected void refreshFilters() {
}
/**
* Sets the tables readonly or not
*
* @param enabled
* to set the table readonly or not
*/
public void setEnabled(boolean enabled) {
addButton.setEnabled(enabled);
downButton.setEnabled(enabled);
removeButton.setEnabled(enabled);
table.setEnabled(enabled);
upButton.setEnabled(enabled);
downButton.setEnabled(enabled);
}
/**
* @return if the table is enabled
*/
public boolean isEnabled() {
return table.isEnabled();
}
/**
* Sets the tooltip text for the viewer
*
* @param tooltip
* the tooltip text
*/
public void setToolTipText(String tooltip) {
addButton.setToolTipText(tooltip);
downButton.setToolTipText(tooltip);
removeButton.setToolTipText(tooltip);
table.setToolTipText(tooltip);
upButton.setToolTipText(tooltip);
}
/**
* Returns the table.
*
* @return the table.
*/
public Table getTable() {
return table;
}
}