blob: 1ef7fa5a448628554cc97eefa1c15e2ee41fac1b [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.vehicle.ui.composites;
import java.text.DecimalFormat;
import javax.vecmath.Vector3d;
import org.eclipse.apogy.addons.vehicle.ApogyAddonsVehiclePackage;
import org.eclipse.apogy.addons.vehicle.OrientationCorrectionMode;
import org.eclipse.apogy.addons.vehicle.VehiclePoseCorrector;
import org.eclipse.apogy.addons.vehicle.ZCorrectionMode;
import org.eclipse.apogy.common.emf.transaction.ApogyCommonTransactionFacade;
import org.eclipse.apogy.common.math.ApogyCommonMathFacade;
import org.eclipse.apogy.common.math.GeometricUtils;
import org.eclipse.apogy.common.math.Matrix3x3;
import org.eclipse.apogy.common.math.Tuple3d;
import org.eclipse.apogy.common.math.ui.composites.Tuple3dComposite;
import org.eclipse.apogy.core.ApogyCorePackage;
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.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.databinding.FeaturePath;
import org.eclipse.emf.databinding.edit.EMFEditProperties;
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.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
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.Label;
import org.eclipse.swt.widgets.Text;
public class VehiclePoseCorrectorComposite extends Composite {
public static final String DEGREE_STRING = "\u00b0";
private final AdapterFactory adapterFactory = new ComposedAdapterFactory(
ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
private VehiclePoseCorrector vehiclePoseCorrector;
private Adapter orientationCorrectionAdapter;
private Button btnEnable;
private Button btnReinitialize;
private ComboViewer comboZCorrectionMode;
private ComboViewer comboOrientationCorrectionMode;
private Text txtZCorrection;
private Tuple3dComposite orientationCorrectionComposite;
private final Tuple3d orientationCorrection = ApogyCommonMathFacade.INSTANCE.createTuple3d(0, 0, 0);
private final DecimalFormat zCorrectionFormat = new DecimalFormat("0.000");
private DataBindingContext m_bindingContext;
public VehiclePoseCorrectorComposite(Composite parent, int style) {
super(parent, style);
setLayout(new GridLayout(3, false));
Label lblEnable = new Label(this, SWT.NONE);
lblEnable.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
lblEnable.setText("Enabled :");
this.btnEnable = new Button(this, SWT.CHECK);
this.btnReinitialize = new Button(this, SWT.NONE);
this.btnReinitialize
.setToolTipText("Forces re-initialization of the pose corrector meshes contact geometries.");
this.btnReinitialize.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
this.btnReinitialize.setText("Re-Initialize");
this.btnReinitialize.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
if (getVehiclePoseCorrector() != null) {
// Run this in a job.
Job job = new Job("") {
@Override
protected IStatus run(IProgressMonitor monitor) {
getVehiclePoseCorrector().reInitialize();
return Status.OK_STATUS;
}
};
job.schedule();
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
Label lblZCorrectionMode = new Label(this, SWT.NONE);
lblZCorrectionMode.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
lblZCorrectionMode.setText("Z Correction Mode:");
this.comboZCorrectionMode = new ComboViewer(this, SWT.NONE);
this.comboZCorrectionMode.getCombo().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
this.comboZCorrectionMode.setContentProvider(new ArrayContentProvider());
this.comboZCorrectionMode.setLabelProvider(new AdapterFactoryLabelProvider(this.adapterFactory));
this.comboZCorrectionMode.setInput(ZCorrectionMode.values());
Label lblOrientationCorrectionMode = new Label(this, SWT.NONE);
lblOrientationCorrectionMode.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
lblOrientationCorrectionMode.setText("Orientation Correction Mode:");
this.comboOrientationCorrectionMode = new ComboViewer(this, SWT.NONE);
this.comboOrientationCorrectionMode.getCombo()
.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
this.comboOrientationCorrectionMode.setContentProvider(new ArrayContentProvider());
this.comboOrientationCorrectionMode.setLabelProvider(new AdapterFactoryLabelProvider(this.adapterFactory));
this.comboOrientationCorrectionMode.setInput(OrientationCorrectionMode.values());
Label lblCurrentZCorrectionm = new Label(this, SWT.NONE);
lblCurrentZCorrectionm.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
lblCurrentZCorrectionm.setText("Z Correction (m):");
this.txtZCorrection = new Text(this, SWT.BORDER);
this.txtZCorrection.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
this.txtZCorrection.setEditable(false);
Label lblCurrentOrientationCorrection = new Label(this, SWT.NONE);
lblCurrentOrientationCorrection.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
lblCurrentOrientationCorrection.setText("Orientation Correction (" + DEGREE_STRING + "):");
this.orientationCorrectionComposite = new Tuple3dComposite(this, SWT.NONE, "0.00");
GridData gd_orientation = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1);
gd_orientation.widthHint = 300;
gd_orientation.minimumWidth = 300;
this.orientationCorrectionComposite.setLayoutData(gd_orientation);
this.orientationCorrectionComposite.setEnableEditing(false);
this.orientationCorrectionComposite.setTuple3d(this.orientationCorrection);
enableControls(false);
// Dispose
addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
if (VehiclePoseCorrectorComposite.this.m_bindingContext != null)
VehiclePoseCorrectorComposite.this.m_bindingContext.dispose();
if (VehiclePoseCorrectorComposite.this.vehiclePoseCorrector != null)
VehiclePoseCorrectorComposite.this.vehiclePoseCorrector.eAdapters()
.remove(getOrientationCorrectionAdapter());
}
});
}
public VehiclePoseCorrector getVehiclePoseCorrector() {
return this.vehiclePoseCorrector;
}
public void setVehiclePoseCorrector(VehiclePoseCorrector vehiclePoseCorrector) {
if (vehiclePoseCorrector != null)
vehiclePoseCorrector.eAdapters().remove(getOrientationCorrectionAdapter());
if (this.m_bindingContext != null)
this.m_bindingContext.dispose();
this.vehiclePoseCorrector = vehiclePoseCorrector;
// Enables / disabled the controls.
enableControls(vehiclePoseCorrector != null);
if (vehiclePoseCorrector != null) {
this.m_bindingContext = customInitDataBindings();
vehiclePoseCorrector.eAdapters().add(getOrientationCorrectionAdapter());
}
}
public void enableControls(boolean enabled) {
if (this.btnEnable != null && !this.btnEnable.isDisposed())
this.btnEnable.setEnabled(enabled);
if (this.btnReinitialize != null && !this.btnReinitialize.isDisposed())
this.btnReinitialize.setEnabled(enabled);
if (this.txtZCorrection != null && !this.txtZCorrection.isDisposed())
this.txtZCorrection.setEnabled(enabled);
if (this.orientationCorrectionComposite != null && !this.orientationCorrectionComposite.isDisposed())
this.orientationCorrectionComposite.setEnabled(enabled);
if (this.comboZCorrectionMode != null && this.comboZCorrectionMode.getCombo() != null
&& !this.comboZCorrectionMode.getCombo().isDisposed()) {
this.comboZCorrectionMode.getControl().setEnabled(enabled);
this.comboZCorrectionMode.getCombo().setEnabled(enabled);
}
if (this.comboOrientationCorrectionMode != null && this.comboOrientationCorrectionMode.getCombo() != null
&& !this.comboOrientationCorrectionMode.getCombo().isDisposed()) {
this.comboOrientationCorrectionMode.getControl().setEnabled(enabled);
this.comboOrientationCorrectionMode.getCombo().setEnabled(enabled);
}
}
@SuppressWarnings("unchecked")
protected DataBindingContext customInitDataBindings() {
DataBindingContext bindingContext = new DataBindingContext();
/* Enabled. */
IObservableValue<Double> observeEnabled = EMFEditProperties
.value(ApogyCommonTransactionFacade.INSTANCE.getDefaultEditingDomain(),
FeaturePath.fromList(ApogyCorePackage.Literals.ABSTRACT_APOGY_SYSTEM_POSE_CORRECTOR__ENABLED))
.observe(this.vehiclePoseCorrector);
IObservableValue<String> observeEnabledButtton = WidgetProperties.selection().observe(this.btnEnable);
bindingContext.bindValue(observeEnabledButtton, observeEnabled, new UpdateValueStrategy(),
new UpdateValueStrategy());
/* Z Correction Value. */
IObservableValue<Double> observeZCorrection = EMFEditProperties
.value(ApogyCommonTransactionFacade.INSTANCE.getDefaultEditingDomain(),
FeaturePath.fromList(ApogyAddonsVehiclePackage.Literals.VEHICLE_POSE_CORRECTOR__ZCORRECTION))
.observe(this.vehiclePoseCorrector);
IObservableValue<String> observeZCorrectionTxt = WidgetProperties.text(SWT.Modify).observe(this.txtZCorrection);
bindingContext.bindValue(observeZCorrectionTxt, observeZCorrection,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER),
new UpdateValueStrategy().setConverter(new Converter(Double.class, String.class) {
@Override
public Object convert(Object fromObject) {
return VehiclePoseCorrectorComposite.this.zCorrectionFormat.format(fromObject);
}
}));
/* Z Correction enablement. */
IObservableValue<String> observeZCorrectionEnable = WidgetProperties.enabled().observe(this.txtZCorrection);
bindingContext.bindValue(observeZCorrectionEnable, observeEnabled, new UpdateValueStrategy(),
new UpdateValueStrategy());
/* Orientation correction enablement */
IObservableValue<String> observeOrientationCorrectionEnable = WidgetProperties.enabled()
.observe(this.orientationCorrectionComposite);
bindingContext.bindValue(observeOrientationCorrectionEnable, observeEnabled, new UpdateValueStrategy(),
new UpdateValueStrategy());
/* Z Correction Mode. */
IObservableValue<Double> observeZCorrectionMode = EMFEditProperties
.value(ApogyCommonTransactionFacade.INSTANCE.getDefaultEditingDomain(),
FeaturePath
.fromList(ApogyAddonsVehiclePackage.Literals.VEHICLE_POSE_CORRECTOR__ZCORRECTION_MODE))
.observe(this.vehiclePoseCorrector);
IObservableValue<?> observeZCorrectionModeCombViewer = ViewerProperties.singleSelection()
.observe(this.comboZCorrectionMode);
bindingContext.bindValue(observeZCorrectionModeCombViewer, observeZCorrectionMode, new UpdateValueStrategy(),
new UpdateValueStrategy());
/* Orientation Correction Mode. */
IObservableValue<Double> observeOrientationCorrectionMode = EMFEditProperties
.value(ApogyCommonTransactionFacade.INSTANCE.getDefaultEditingDomain(),
FeaturePath.fromList(
ApogyAddonsVehiclePackage.Literals.VEHICLE_POSE_CORRECTOR__ORIENTATION_CORRECTION_MODE))
.observe(this.vehiclePoseCorrector);
IObservableValue<?> observeOrientationCorrectionModeComboViewer = ViewerProperties.singleSelection()
.observe(this.comboOrientationCorrectionMode);
bindingContext.bindValue(observeOrientationCorrectionModeComboViewer, observeOrientationCorrectionMode,
new UpdateValueStrategy(), new UpdateValueStrategy());
return bindingContext;
}
protected Adapter getOrientationCorrectionAdapter() {
if (this.orientationCorrectionAdapter == null) {
this.orientationCorrectionAdapter = new AdapterImpl() {
@Override
public void notifyChanged(Notification msg) {
if (msg.getNotifier() instanceof VehiclePoseCorrector) {
int featureID = msg.getFeatureID(VehiclePoseCorrector.class);
if (featureID == ApogyAddonsVehiclePackage.VEHICLE_POSE_CORRECTOR__ORIENTATION_CORRECTION) {
if (msg.getNewValue() instanceof Matrix3x3) {
Matrix3x3 rot = (Matrix3x3) msg.getNewValue();
Vector3d r = GeometricUtils.extractRotationFromXYZRotMatrix(rot.asMatrix3d());
VehiclePoseCorrectorComposite.this.orientationCorrection.setX(Math.toDegrees(r.x));
VehiclePoseCorrectorComposite.this.orientationCorrection.setY(Math.toDegrees(r.y));
VehiclePoseCorrectorComposite.this.orientationCorrection.setZ(Math.toDegrees(r.z));
}
}
}
}
};
}
return this.orientationCorrectionAdapter;
}
}