blob: 6fd9df91177a29ec30afd31288a975a28a5a7586 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2018 Agence spatiale canadienne / Canadian Space Agency
* 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:
* Pierre Allard,
* Regent L'Archeveque,
* Olivier L. Larouche - initial API and implementation
*
* SPDX-License-Identifier: EPL-1.0
*
*******************************************************************************/
package org.eclipse.apogy.core.invocator.ui.composites;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.List;
import org.eclipse.apogy.common.emf.ApogyCommonEMFPackage;
import org.eclipse.apogy.common.emf.transaction.ApogyCommonTransactionFacade;
import org.eclipse.apogy.common.emf.ui.ApogyCommonEMFUIFactory;
import org.eclipse.apogy.common.emf.ui.NamedSetting;
import org.eclipse.apogy.common.emf.ui.wizards.ApogyEObjectWizard;
import org.eclipse.apogy.core.invocator.ApogyCoreInvocatorFacade;
import org.eclipse.apogy.core.invocator.ApogyCoreInvocatorPackage;
import org.eclipse.apogy.core.invocator.InitialConditions;
import org.eclipse.apogy.core.invocator.InitialConditionsList;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.conversion.Converter;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.core.databinding.property.Properties;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.databinding.EMFProperties;
import org.eclipse.emf.databinding.FeaturePath;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
import org.eclipse.jface.databinding.viewers.ViewerProperties;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
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.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class InitialConditionsListComposite extends Composite {
private static final Logger Logger = LoggerFactory.getLogger(InitialConditionsListComposite.class);
private InitialConditionsList initialConditionsList;
private final WritableValue<InitialConditionsList> initialConditionsBinder = new WritableValue<InitialConditionsList>();
private final TableViewer tableViewer;
private final Button btnNew;
private final Button btnDelete;
private final Button btnCollect;
private final Button btnApply;
private DataBindingContext m_currentDataBindings;
public InitialConditionsListComposite(Composite parent, int style) {
super(parent, style);
setLayout(new GridLayout(1, false));
Composite composite = new Composite(this, SWT.NONE);
composite.setLayout(new GridLayout(2, false));
this.tableViewer = new TableViewer(composite, SWT.BORDER | SWT.FULL_SELECTION);
Table table = this.tableViewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
GridData gd_table = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 5);
gd_table.widthHint = 300;
gd_table.minimumWidth = 300;
table.setLayoutData(gd_table);
this.tableViewer.setContentProvider(new CustomContentProvider());
this.tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection iStructuredSelection = ((IStructuredSelection) event.getSelection());
newInitialConditionsSelected((InitialConditions) iStructuredSelection.getFirstElement());
}
});
TableColumn tblclmnName = new TableColumn(table, SWT.NONE);
tblclmnName.setText("Name");
TableColumn tblclmnDescription = new TableColumn(table, SWT.NONE);
tblclmnDescription.setText("Description");
this.btnNew = new Button(composite, SWT.None);
this.btnNew.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
this.btnNew.setText("New");
this.btnNew.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event event) {
if (event.type == SWT.Selection) {
NamedSetting namedSettings = ApogyCommonEMFUIFactory.eINSTANCE.createNamedSetting();
namedSettings.setParent(getInitialConditionsList());
namedSettings.setContainingFeature(
ApogyCoreInvocatorPackage.Literals.INITIAL_CONDITIONS_LIST__INITIAL_CONDITIONS);
ApogyEObjectWizard wizard = new ApogyEObjectWizard(
ApogyCoreInvocatorPackage.Literals.INITIAL_CONDITIONS_LIST__INITIAL_CONDITIONS,
getInitialConditionsList(), namedSettings,
ApogyCoreInvocatorPackage.Literals.INITIAL_CONDITIONS);
WizardDialog dialog = new WizardDialog(getShell(), wizard);
if (dialog.open() == Window.OK) {
if (!InitialConditionsListComposite.this.tableViewer.isBusy()) {
// Forces the viewer to refresh its input.
InitialConditionsListComposite.this.tableViewer.refresh();
packColumns();
// Select the newly created InitialCOnditions.
InitialConditionsListComposite.this.tableViewer
.setSelection(new StructuredSelection(wizard.getCreatedEObject()), true);
}
}
}
}
});
this.btnDelete = new Button(composite, SWT.NONE);
this.btnDelete.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false, 1, 1));
this.btnDelete.setText("Delete");
this.btnDelete.setEnabled(false);
this.btnDelete.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
String initialConditionsToDeleteMessage = "";
Iterator<InitialConditions> initialConditionsIterator = getSelectedInitialConditionsList().iterator();
while (initialConditionsIterator.hasNext()) {
InitialConditions initialConditions = initialConditionsIterator.next();
initialConditionsToDeleteMessage = initialConditionsToDeleteMessage + initialConditions.getName();
if (initialConditionsIterator.hasNext()) {
initialConditionsToDeleteMessage = initialConditionsToDeleteMessage + ", ";
}
}
MessageDialog dialog = new MessageDialog(null, "Delete the selected Initial Conditions", null,
"Are you sure to delete these Initial Conditions: " + initialConditionsToDeleteMessage,
MessageDialog.QUESTION, new String[] { "Yes", "No" }, 1);
int result = dialog.open();
if (result == 0) {
for (InitialConditions initialConditions : getSelectedInitialConditionsList()) {
try {
ApogyCommonTransactionFacade.INSTANCE.basicRemove(getInitialConditionsList(),
ApogyCoreInvocatorPackage.Literals.INITIAL_CONDITIONS_LIST__INITIAL_CONDITIONS,
initialConditions);
} catch (Exception e) {
Logger.error(
"Unable to delete the Initial Conditions <" + initialConditions.getName() + ">", e);
}
}
}
// Forces the viewer to refresh its input.
refreshViewer();
}
});
// Filler
new Label(composite, SWT.NONE);
this.btnCollect = new Button(composite, SWT.NONE);
this.btnCollect.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false, 1, 1));
this.btnCollect.setText("Collect");
this.btnCollect.setToolTipText(
"Collects the current states of the Variables and saves them in the selected Initial Conditions.");
this.btnCollect.setEnabled(false);
this.btnCollect.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
InitialConditions selectedInitialConditions = getSelectedInitialConditionsList().get(0);
try {
ApogyCoreInvocatorFacade.INSTANCE.collectInitialConditions(
ApogyCoreInvocatorFacade.INSTANCE.getActiveInvocatorSession().getEnvironment(),
selectedInitialConditions);
} catch (Throwable t) {
Logger.error(t.getMessage(), t);
}
// Forces the viewer to re-select the selection.
InitialConditionsListComposite.this.tableViewer
.setSelection(new StructuredSelection(selectedInitialConditions), true);
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
this.btnApply = new Button(composite, SWT.NONE);
this.btnApply.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false, 1, 1));
this.btnApply.setText("Apply");
this.btnApply.setToolTipText("Applies the selected Initial Conditions to the Variables.");
this.btnApply.setEnabled(false);
this.btnApply.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
final InitialConditions selectedInitialConditions = getSelectedInitialConditionsList().get(0);
IRunnableWithProgress runnable = new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
ApogyCoreInvocatorFacade.INSTANCE.applyInitialConditions(
ApogyCoreInvocatorFacade.INSTANCE.getActiveInvocatorSession().getEnvironment(),
selectedInitialConditions, monitor);
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
try {
new ProgressMonitorDialog(getShell()).run(true, true, runnable);
} catch (Throwable t) {
Logger.error(t.getMessage(), t);
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
// Dispose.
addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
if (InitialConditionsListComposite.this.m_currentDataBindings != null) {
InitialConditionsListComposite.this.m_currentDataBindings.dispose();
}
}
});
}
public void setSelectedInitialConditions(InitialConditions initialConditions) {
if (initialConditions != null) {
this.tableViewer.setSelection(new StructuredSelection(initialConditions), true);
} else {
this.tableViewer.setSelection(null, true);
}
}
@SuppressWarnings("unchecked")
public List<InitialConditions> getSelectedInitialConditionsList() {
return ((IStructuredSelection) this.tableViewer.getSelection()).toList();
}
public InitialConditionsList getInitialConditionsList() {
return this.initialConditionsList;
}
public void setInitialConditionsList(InitialConditionsList initialConditionsList) {
if (this.m_currentDataBindings != null) {
this.m_currentDataBindings.dispose();
}
this.initialConditionsList = initialConditionsList;
if (initialConditionsList != null) {
this.m_currentDataBindings = initDataBindingsCustom();
// tableViewer.setInput(initialConditionsList);
} else {
this.tableViewer.setInput(null);
}
refreshViewer();
}
protected void newInitialConditionsSelected(InitialConditions initialConditions) {
}
@SuppressWarnings("unchecked")
protected DataBindingContext initDataBindingsCustom() {
DataBindingContext bindingContext = new DataBindingContext();
this.initialConditionsBinder.setValue(getInitialConditionsList());
/**
* Context list binding
*/
IObservableList<?> environmentContextListContextsObserveValue = EMFProperties.list(FeaturePath.fromList(
(EStructuralFeature) ApogyCoreInvocatorPackage.Literals.INITIAL_CONDITIONS_LIST__INITIAL_CONDITIONS))
.observeDetail(this.initialConditionsBinder);
ObservableListContentProvider contentProvider = new ObservableListContentProvider();
this.tableViewer.setContentProvider(contentProvider);
this.tableViewer.setLabelProvider(
new ObservableMapLabelProvider(Properties.observeEach(contentProvider.getKnownElements(),
EMFProperties.value(ApogyCommonEMFPackage.Literals.DESCRIBED__DESCRIPTION),
EMFProperties.value(ApogyCommonEMFPackage.Literals.NAMED__NAME))) {
private final static int NAME_COLUMN_ID = 0;
private final static int DESCRIPTION_COLUMN_ID = 1;
@Override
public String getColumnText(Object element, int columnIndex) {
String str = "<undefined>";
if (element instanceof InitialConditions) {
InitialConditions initialConditions = (InitialConditions) element;
switch (columnIndex) {
case NAME_COLUMN_ID:
str = initialConditions.getName();
break;
case DESCRIPTION_COLUMN_ID:
str = initialConditions.getDescription();
break;
}
}
return str;
}
});
this.tableViewer.setInput(environmentContextListContextsObserveValue);
/*
* Delete button enabling bindings.
*/
IObservableValue<?> observeSingleSelectionTableViewer = ViewerProperties.singleSelection()
.observe(this.tableViewer);
IObservableValue<?> observeEnabledBtnDeleteObserveWidget = WidgetProperties.enabled().observe(this.btnDelete);
bindingContext.bindValue(observeEnabledBtnDeleteObserveWidget, observeSingleSelectionTableViewer,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER),
new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE)
.setConverter(new Converter(Object.class, Boolean.class) {
@Override
public Object convert(Object fromObject) {
return fromObject != null;
}
}));
/*
* Collect button enabling bindings.
*/
IObservableValue<?> observeEnabledBtnCollectObserveWidget = WidgetProperties.enabled().observe(this.btnCollect);
bindingContext.bindValue(observeEnabledBtnCollectObserveWidget, observeSingleSelectionTableViewer,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER),
new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE)
.setConverter(new Converter(Object.class, Boolean.class) {
@Override
public Object convert(Object fromObject) {
return fromObject != null;
}
}));
/*
* Apply button enabling bindings.
*/
IObservableValue<?> observeEnabledBtnApplyObserveWidget = WidgetProperties.enabled().observe(this.btnApply);
bindingContext.bindValue(observeEnabledBtnApplyObserveWidget, observeSingleSelectionTableViewer,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER),
new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE)
.setConverter(new Converter(Object.class, Boolean.class) {
@Override
public Object convert(Object fromObject) {
return fromObject != null;
}
}));
return bindingContext;
}
/**
* This methods packs the columns to adjust their widths
*/
private void packColumns() {
if (!this.tableViewer.isBusy()) {
getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
for (TableColumn column : InitialConditionsListComposite.this.tableViewer.getTable().getColumns()) {
column.pack();
}
}
});
}
}
protected void refreshViewer() {
if (!this.tableViewer.isBusy()) {
getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
InitialConditionsListComposite.this.tableViewer.refresh();
packColumns();
}
});
}
}
private class CustomContentProvider implements ITreeContentProvider {
@Override
public void dispose() {
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
@Override
public Object[] getElements(Object inputElement) {
if (inputElement instanceof InitialConditionsList) {
InitialConditionsList list = (InitialConditionsList) inputElement;
return list.getInitialConditions().toArray();
}
return null;
}
@Override
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof InitialConditionsList) {
InitialConditionsList list = (InitialConditionsList) parentElement;
return list.getInitialConditions().toArray();
}
return null;
}
@Override
public Object getParent(Object element) {
return null;
}
@Override
public boolean hasChildren(Object element) {
if (element instanceof InitialConditionsList) {
InitialConditionsList list = (InitialConditionsList) element;
return !list.getInitialConditions().isEmpty();
} else {
return false;
}
}
}
}