| /******************************************************************************* |
| * 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; |
| } |
| } |