blob: bc784cd5b9c74b133975d8ca2629dffeb3a2be7a [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 - initial API and implementation
* Regent L'Archeveque
* SPDX-License-Identifier: EPL-1.0
*******************************************************************************/
package org.eclipse.apogy.addons.geometry.paths.ui.composites;
import java.util.Collection;
import org.eclipse.apogy.addons.geometry.paths.ApogyAddonsGeometryPathsPackage;
import org.eclipse.apogy.addons.geometry.paths.WayPointPath;
import org.eclipse.apogy.common.emf.transaction.ApogyCommonTransactionFacade;
import org.eclipse.apogy.common.emf.transaction.impl.ApogyCommonTransactionFacadeCustomImpl;
import org.eclipse.apogy.common.emf.ui.wizards.ApogyEObjectWizard;
import org.eclipse.apogy.common.geometry.data.ApogyCommonGeometryDataPackage;
import org.eclipse.apogy.common.geometry.data3d.ApogyCommonGeometryData3DPackage;
import org.eclipse.apogy.common.geometry.data3d.CartesianPositionCoordinates;
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.value.IObservableValue;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.databinding.viewers.ViewerProperties;
import org.eclipse.jface.dialogs.MessageDialog;
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.TreeViewer;
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.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.Tree;
public class WayPointPathListComposite extends Composite {
private EObject owner = null;
private EStructuralFeature feature = null;
private final boolean enableEditing;
private Adapter adapter;
private final ComposedAdapterFactory adapterFactory = new ComposedAdapterFactory(
ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
private final Tree tree;
private final TreeViewer treeViewer;
private Button btnNewPath;
private Button btnNewPoint;
private Button btnDelete;
private DataBindingContext m_bindingContext;
/**
*
* @param parent
* @param style
* @param enableEditing Whether or not to provided editing support to create and
* delete WaypointPath or point within paths.
* @param owner The eObject containing the feature which refers to a
* list of WayPointPath.
* @param feature The feature which refers to a list of WayPointPath.
*/
public WayPointPathListComposite(Composite parent, int style, boolean enableEditing, EObject owner,
EStructuralFeature feature) {
super(parent, style);
this.enableEditing = enableEditing;
this.owner = owner;
this.feature = feature;
setLayout(new GridLayout(3, false));
// Table Viewer
this.treeViewer = new TreeViewer(this,
SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);
this.tree = this.treeViewer.getTree();
GridData gd_tree = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
gd_tree.widthHint = 200;
gd_tree.minimumWidth = 200;
this.tree.setLayoutData(gd_tree);
this.tree.setLinesVisible(true);
this.treeViewer.setContentProvider(new WayPoinPathListContentProvider());
this.treeViewer.setLabelProvider(new AdapterFactoryLabelProvider(this.adapterFactory));
this.treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
Object selected = ((IStructuredSelection) event.getSelection()).getFirstElement();
if (selected instanceof WayPointPath) {
newWayPointPathSelected((WayPointPath) selected);
} else if (selected instanceof CartesianPositionCoordinates) {
newCartesianPositionCoordinatesSelected((CartesianPositionCoordinates) selected);
}
}
});
if (enableEditing) {
Composite compositeButtons = new Composite(this, SWT.NONE);
compositeButtons.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1));
compositeButtons.setLayout(new GridLayout(1, false));
this.btnNewPath = new Button(compositeButtons, SWT.NONE);
this.btnNewPath.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
this.btnNewPath.setBounds(0, 0, 92, 33);
this.btnNewPath.setText("New Path");
this.btnNewPath.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
if (getOwner() != null && getFeature() != null) {
ApogyEObjectWizard wizard = new ApogyEObjectWizard((EReference) getFeature(), getOwner(), null,
ApogyAddonsGeometryPathsPackage.Literals.WAY_POINT_PATH);
WizardDialog dialog = new WizardDialog(getShell(), wizard);
if (dialog.open() == Window.OK)
;
{
// Gets the WayPointPath just created.
WayPointPath newWayPointPath = (WayPointPath) wizard.getCreatedEObject();
// Forces the viewer to refresh its input.
if (!WayPointPathListComposite.this.treeViewer.isBusy()) {
WayPointPathListComposite.this.treeViewer.setInput(getOwner().eGet(getFeature(), true));
WayPointPathListComposite.this.treeViewer
.setSelection(new StructuredSelection(newWayPointPath));
}
}
}
}
});
this.btnNewPoint = new Button(compositeButtons, SWT.NONE);
this.btnNewPoint.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
this.btnNewPoint.setText("New Point");
this.btnNewPoint.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
if (getOwner() != null && getFeature() != null) {
Object selected = WayPointPathListComposite.this.treeViewer.getStructuredSelection()
.getFirstElement();
WayPointPath wayPointPath = null;
if (selected instanceof WayPointPath) {
wayPointPath = (WayPointPath) selected;
} else if (selected instanceof CartesianPositionCoordinates) {
CartesianPositionCoordinates cartesianPositionCoordinates = (CartesianPositionCoordinates) selected;
if (cartesianPositionCoordinates.eContainer() instanceof WayPointPath) {
wayPointPath = (WayPointPath) cartesianPositionCoordinates.eContainer();
}
}
if (wayPointPath != null) {
ApogyEObjectWizard wizard = new ApogyEObjectWizard(
ApogyCommonGeometryDataPackage.Literals.COORDINATES_SET__POINTS, wayPointPath, null,
ApogyCommonGeometryData3DPackage.Literals.CARTESIAN_POSITION_COORDINATES);
WizardDialog dialog = new WizardDialog(getShell(), wizard);
if (dialog.open() == Window.OK)
;
{
// Gets the point just created.
CartesianPositionCoordinates newPoint = (CartesianPositionCoordinates) wizard
.getCreatedEObject();
// Forces the viewer to refresh its input.
if (!WayPointPathListComposite.this.treeViewer.isBusy()) {
WayPointPathListComposite.this.treeViewer
.setInput(getOwner().eGet(getFeature(), true));
WayPointPathListComposite.this.treeViewer
.setSelection(new StructuredSelection(newPoint));
}
}
}
}
}
});
this.btnDelete = new Button(compositeButtons, SWT.NONE);
this.btnDelete.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
this.btnDelete.setBounds(0, 0, 92, 33);
this.btnDelete.setText("Delete");
this.btnDelete.addSelectionListener(new SelectionAdapter() {
@SuppressWarnings("unchecked")
@Override
public void widgetSelected(SelectionEvent event) {
if (getOwner() != null && getFeature() != null) {
Object selected = WayPointPathListComposite.this.treeViewer.getStructuredSelection()
.getFirstElement();
if (selected instanceof CartesianPositionCoordinates) {
CartesianPositionCoordinates pointToDelete = (CartesianPositionCoordinates) selected;
MessageDialog dialog = new MessageDialog(null, "Delete the selected way point", null,
"Are you sure to delete this way point ?", MessageDialog.QUESTION,
new String[] { "Yes", "No" }, 1);
int result = dialog.open();
if (result == 0) {
if (ApogyCommonTransactionFacade.INSTANCE.areEditingDomainsValid(
pointToDelete.eContainer(),
ApogyCommonGeometryDataPackage.Literals.COORDINATES_SET__POINTS, pointToDelete,
false) == ApogyCommonTransactionFacadeCustomImpl.EXECUTE_COMMAND_ON_OWNER_DOMAIN) {
ApogyCommonTransactionFacade.INSTANCE.basicDelete(pointToDelete.eContainer(),
ApogyCommonGeometryDataPackage.Literals.COORDINATES_SET__POINTS,
pointToDelete);
} else {
if (pointToDelete.eContainer() instanceof WayPointPath) {
WayPointPath wayPointPath = (WayPointPath) pointToDelete.eContainer();
wayPointPath.getPoints().remove(pointToDelete);
}
}
}
} else if (selected instanceof WayPointPath) {
MessageDialog dialog = new MessageDialog(null, "Delete the selected way point path", null,
"Are you sure to delete this way point path ?", MessageDialog.QUESTION,
new String[] { "Yes", "No" }, 1);
int result = dialog.open();
if (result == 0) {
WayPointPath wayPointPathToDelete = (WayPointPath) selected;
if (ApogyCommonTransactionFacade.INSTANCE.areEditingDomainsValid(getOwner(),
getFeature(), wayPointPathToDelete,
false) == ApogyCommonTransactionFacadeCustomImpl.EXECUTE_COMMAND_ON_OWNER_DOMAIN) {
ApogyCommonTransactionFacade.INSTANCE.basicDelete(getOwner(), getFeature(),
wayPointPathToDelete);
} else if (getOwner().eGet(getFeature(), true) instanceof Collection) {
Collection<WayPointPath> collection = (Collection<WayPointPath>) getOwner()
.eGet(getFeature());
collection.remove(wayPointPathToDelete);
}
}
}
// Forces the viewer to refresh its input.
if (!WayPointPathListComposite.this.treeViewer.isBusy()) {
WayPointPathListComposite.this.treeViewer.setInput(getOwner().eGet(getFeature(), true));
}
}
}
});
}
// Sets initial list
if (getOwner() != null) {
if (getFeature() != null) {
Object value = getOwner().eGet(getFeature(), true);
if (value instanceof Collection) {
this.treeViewer.setInput(value);
} else {
this.treeViewer.setInput(null);
}
}
}
this.m_bindingContext = customInitDataBindings();
// Dispose
addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
if (WayPointPathListComposite.this.m_bindingContext != null)
WayPointPathListComposite.this.m_bindingContext.dispose();
// Unregister from owner.
getOwner().eAdapters().remove(getAdapter());
}
});
}
public EObject getOwner() {
return this.owner;
}
public void setOwner(EObject newOwner) {
if (this.m_bindingContext != null)
this.m_bindingContext.dispose();
// Un-Register listener from past owner.
if (this.owner != null) {
this.owner.eAdapters().remove(getAdapter());
}
this.owner = newOwner;
if (newOwner != null) {
if (getFeature() != null) {
// Update the color.
Object value = newOwner.eGet(getFeature(), true);
if (value instanceof Collection) {
this.treeViewer.setInput(value);
} else {
this.treeViewer.setInput(null);
}
}
// Register listener to the new owner.
newOwner.eAdapters().add(getAdapter());
this.m_bindingContext = customInitDataBindings();
}
}
public EStructuralFeature getFeature() {
return this.feature;
}
public void setFeature(EStructuralFeature feature) {
if (this.m_bindingContext != null)
this.m_bindingContext.dispose();
this.feature = feature;
// Update displayed color.
if (getOwner() != null && feature != null) {
Object value = getOwner().eGet(getFeature(), true);
if (value instanceof Collection) {
this.treeViewer.setInput(value);
} else {
this.treeViewer.setInput(null);
}
this.m_bindingContext = customInitDataBindings();
} else {
this.treeViewer.setInput(null);
}
}
protected void newWayPointPathSelected(WayPointPath wayPointPath) {
}
protected void newCartesianPositionCoordinatesSelected(
CartesianPositionCoordinates newCartesianPositionCoordinates) {
}
protected DataBindingContext customInitDataBindings() {
DataBindingContext bindingContext = new DataBindingContext();
IObservableValue<?> observeSingleSelectionViewer = ViewerProperties.singleSelection().observe(this.treeViewer);
if (this.enableEditing) {
/* Delete Button Enabled Binding. */
IObservableValue<?> observeEnabledBtnDeleteObserveWidget = WidgetProperties.enabled()
.observe(this.btnDelete);
bindingContext.bindValue(observeEnabledBtnDeleteObserveWidget, observeSingleSelectionViewer, null,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE)
.setConverter(new Converter(Object.class, Boolean.class) {
@Override
public Object convert(Object fromObject) {
return fromObject != null;
}
}));
/* New Point Enabled Binding. */
IObservableValue<?> observeEnabledBtnNewPointObserveWidget = WidgetProperties.enabled()
.observe(this.btnNewPoint);
bindingContext.bindValue(observeEnabledBtnNewPointObserveWidget, observeSingleSelectionViewer, null,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE)
.setConverter(new Converter(Object.class, Boolean.class) {
@Override
public Object convert(Object fromObject) {
return fromObject instanceof WayPointPath;
}
}));
}
return bindingContext;
}
private class WayPoinPathListContentProvider 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 Collection<?>) {
Collection<?> paths = (Collection<?>) inputElement;
return paths.toArray();
} else if (inputElement instanceof WayPointPath) {
WayPointPath wayPointPath = (WayPointPath) inputElement;
return wayPointPath.getPoints().toArray();
}
return null;
}
@Override
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof Collection<?>) {
Collection<?> paths = (Collection<?>) parentElement;
return paths.toArray();
} else if (parentElement instanceof WayPointPath) {
WayPointPath wayPointPath = (WayPointPath) parentElement;
return wayPointPath.getPoints().toArray();
}
return null;
}
@Override
public Object getParent(Object element) {
return null;
}
@Override
public boolean hasChildren(Object element) {
if (element instanceof Collection<?>) {
Collection<?> paths = (Collection<?>) element;
return !paths.isEmpty();
} else if (element instanceof WayPointPath) {
WayPointPath wayPointPath = (WayPointPath) element;
return !wayPointPath.getPoints().isEmpty();
}
return false;
}
}
private Adapter getAdapter() {
if (this.adapter == null) {
this.adapter = new AdapterImpl() {
@Override
public void notifyChanged(Notification msg) {
if (msg.getFeature() == getFeature()) {
if (msg.getNewValue() instanceof Collection) {
WayPointPathListComposite.this.treeViewer.setInput(msg.getNewValue());
} else {
WayPointPathListComposite.this.treeViewer.setInput(null);
}
}
}
};
}
return this.adapter;
}
}