blob: 2e93ba0336dea72bd9deb1bff0a7a7f6c8f7fc39 [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,
* Olivier L. Larouche
*
* SPDX-License-Identifier: EPL-1.0
*******************************************************************************/
package org.eclipse.apogy.common.emf.ui.composites;
import java.text.DecimalFormat;
import javax.measure.converter.ConversionException;
import javax.measure.unit.Unit;
import org.eclipse.apogy.common.emf.ApogyCommonEMFFacade;
import org.eclipse.apogy.common.emf.Ranges;
import org.eclipse.apogy.common.emf.transaction.ApogyCommonTransactionFacade;
import org.eclipse.apogy.common.emf.ui.ApogyCommonEMFUIFacade;
import org.eclipse.apogy.common.emf.ui.ApogyCommonEMFUIFactory;
import org.eclipse.apogy.common.emf.ui.SimpleFormatProvider;
import org.eclipse.apogy.common.emf.ui.SimpleUnitsProvider;
import org.eclipse.apogy.common.emf.ui.dialogs.SelectUnitDialog;
import org.eclipse.apogy.common.emf.ui.preferences.PreferencesConstants;
import org.eclipse.core.databinding.Binding;
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.util.EMap;
import org.eclipse.emf.databinding.EMFProperties;
import org.eclipse.emf.databinding.FeaturePath;
import org.eclipse.emf.databinding.edit.EMFEditProperties;
import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.ETypedElement;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.window.Window;
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.graphics.Color;
import org.eclipse.swt.graphics.GC;
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TypedElementSimpleUnitsComposite extends Composite {
private static final Logger Logger = LoggerFactory.getLogger(TypedElementSimpleUnitsComposite.class);
private DataBindingContext bindingContext;
private Binding valueBinding;
private Binding colorBinding;
private IPropertyChangeListener propertyChangeListener;
private EObject eObject;
private FeaturePath featurePath;
private String noValueText = "";
// private boolean showLabel = true;
// private boolean showUnits = true;
// private boolean showUnitsButton = true;
private int labelWidth = -1;
// private int valueWidth = -1;
// private int buttonUnitsWidth = -1;
private Label nameLabel;
private final Text valueText;
private Button unitsButton;
private Label unitsLabel;
/**
* Create a TypedElementSimpleUnitsComposite with defaults settings.
*
* @param parent The parent composite.
* @param style The style of the composite.
*/
public TypedElementSimpleUnitsComposite(Composite parent, int style) {
this(parent, style, true, true, "");
}
/**
* Creates a TypedElementSimpleUnitsComposite with detailed settings.
*
* @param parent The parent composite.
* @param style The style of the composite.
* @param showLabel True to show the label in front of the values, false
* not to show it.
* @param showUnitsButton True to show the button used to change displayed
* units, false to hide it.
* @param showUnits True to show the units as a label, false to hide it.
* Does nothing if showUnitsButton is true.
* @param noValueText String to display when no value is available.
*/
public TypedElementSimpleUnitsComposite(Composite parent, int style, boolean showLabel, boolean showUnitsButton,
boolean showUnits, String noValueText) {
this(parent, style, showLabel, showUnitsButton, showUnits, noValueText, -1, -1, -1);
}
/**
* Creates a TypedElementSimpleUnitsComposite with detailed settings.
*
* @param parent The parent composite.
* @param style The style of the composite.
* @param showLabel True to show the label in front of the values, false
* not to show it.
* @param showUnitsButton True to show the button used to change displayed
* units, false to hide it.
* @param noValueText String to display when no value is available.
*/
public TypedElementSimpleUnitsComposite(Composite parent, int style, boolean showLabel, boolean showUnitsButton,
String noValueText) {
this(parent, style, showLabel, showUnitsButton, false, noValueText);
}
/**
* Creates a TypedElementSimpleUnitsComposite with detailed settings.
*
* @param parent The parent composite.
* @param style The style of the composite.
* @param showLabel True to show the label in front of the values, false
* not to show it.
* @param showUnitsButton True to show the button used to change displayed
* units, false to hide it.
* @param showUnits True to show the units as a label, false to hide it.
* Does nothing if showUnitsButton is true.
* @param noValueText String to display when no value is available.
* @param labelWidth The desired width of the feature label, -1 to fill.
* @param valueWidth The desired width of the value text, -1 to fill.
* @param buttonUnitsWidth The desired width of the units label or units button,
* -1 to fill.
*
*/
public TypedElementSimpleUnitsComposite(Composite parent, int style, boolean showLabel, boolean showUnitsButton,
boolean showUnits, String noValueText, int labelWidth, int valueWidth, int buttonUnitsWidth) {
super(parent, style);// private boolean showLabel = true;
// private boolean showUnits = true;
// private boolean showUnitsButton = true;
this.noValueText = noValueText;
// this.showLabel = showLabel;
// this.showUnits = showUnits;
// this.showUnitsButton = showUnitsButton;
this.labelWidth = labelWidth;
// this.valueWidth = valueWidth;
// this.buttonUnitsWidth = buttonUnitsWidth;
/** Preference listener */
org.eclipse.apogy.common.emf.ui.Activator.getDefault().getPreferenceStore()
.addPropertyChangeListener(getPropertyChangeListener());
// Determine how many columns we need.
int gridSize = 1;
if (showLabel) {
gridSize += 1;
}
if (showUnitsButton || showUnits) {
gridSize += 1;
}
GridLayout layout = new GridLayout(gridSize, false);
layout.marginHeight = 0;
layout.marginBottom = 0;
layout.marginTop = 0;
layout.marginLeft = 0;
layout.marginRight = 0;
setLayout(layout);
// Add the label if required.
if (showLabel) {
this.nameLabel = createFeatureLabel(this, this.labelWidth);
}
/** Value */
this.valueText = getValueText(this, valueWidth);
this.valueText.setText(getNoValueText());
this.valueText.setEditable(isFeatureEditable());
// Adds the button is required.
if (showUnitsButton) {
/** Units button */
this.unitsButton = createUnitsButton(this, buttonUnitsWidth);
this.unitsButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
SelectUnitDialog dialog = new SelectUnitDialog(getShell(),
resolveValue(TypedElementSimpleUnitsComposite.this.eObject,
TypedElementSimpleUnitsComposite.this.featurePath),
getDecimalFormat(), getNativeUnits(), getDisplayUnits()) {
@Override
protected void buttonPressed(int buttonId) {
if (buttonId == OK) {
try {
/**
* If the format registry needs to be updated
*/
if (getDecimalFormat() != getResultFormat()) {
/** Create a format provider */
SimpleFormatProvider formatProvider = ApogyCommonEMFUIFactory.eINSTANCE
.createSimpleFormatProvider();
formatProvider.setFormatPattern(getResultFormat().toPattern());
/** Update the format registry */
ApogyCommonEMFUIFacade.INSTANCE
.addFormatProviderToRegistry(getEStructuralFeature(), formatProvider);
}
/** If the units registry needs to be updated */
if (getDisplayUnits() != getResultUnit()) {
/** Create a units provider */
SimpleUnitsProvider unitsProvider = ApogyCommonEMFUIFactory.eINSTANCE
.createSimpleUnitsProvider();
unitsProvider.setUnit(getResultUnit());
/** Update the units registry */
ApogyCommonEMFUIFacade.INSTANCE
.addUnitsProviderToRegistry(getEStructuralFeature(), unitsProvider);
}
} catch (ConversionException e) {
Logger.error("The value can not be converted ");
}
}
super.buttonPressed(buttonId);
}
};
dialog.open();
if (dialog.getReturnCode() == Window.OK) {
updateButton();
updateValueTooltip();
updateUnitsLabel();
TypedElementSimpleUnitsComposite.this.valueBinding.updateModelToTarget();
}
}
});
} else if (showUnits) {
this.unitsLabel = createUnitsLabel(this, buttonUnitsWidth);
}
// Adds a dispose listener.
addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
if (TypedElementSimpleUnitsComposite.this.propertyChangeListener != null) {
org.eclipse.apogy.common.emf.ui.Activator.getDefault().getPreferenceStore()
.removePropertyChangeListener(getPropertyChangeListener());
}
}
});
}
/**
* Sets the value to be displayed in the composite
*
* @param eStructuralFeature The structural feature being displayed
* @param instance The instance that the feature refers to.
*/
public void setTypedElement(final EStructuralFeature eStructuralFeature, final EObject instance) {
if (this.bindingContext != null) {
this.bindingContext.dispose();
}
this.eObject = instance;
if (eStructuralFeature != null) {
this.featurePath = FeaturePath.fromList(eStructuralFeature);
} else {
this.featurePath = null;
}
if (this.nameLabel != null) {
if ("".equals(getLabelText())) {
this.nameLabel.setText(getLabelFromEStructuralFeature(getEStructuralFeature()) + " :");
}
}
if (instance != null && eStructuralFeature != null) {
initDataBindingsCustom();
updateButton();
updateUnitsLabel();
updateValueTooltip();
}
layout();
}
/**
* Sets the value to be displayed in the composite
*
* @param featurePath The FeaturePath reffering to a particular structural
* feature being displayed
* @param instance The instance that the feature refers to.
*/
public void setTypedElement(final FeaturePath featurePath, final EObject instance) {
if (this.bindingContext != null) {
this.bindingContext.dispose();
}
this.eObject = instance;
this.featurePath = featurePath;
if (this.nameLabel != null) {
if ("".equals(getLabelText())) {
this.nameLabel.setText(getLabelFromEStructuralFeature(getEStructuralFeature()) + " : ");
}
}
if (instance != null && getEStructuralFeature() != null) {
initDataBindingsCustom();
updateButton();
updateUnitsLabel();
updateValueTooltip();
}
layout();
}
/**
* Set the instance that refers to the value to display.
*
* @param instance The instance.
*/
public void setInstance(EObject instance) {
this.eObject = instance;
if (instance != null && getEStructuralFeature() != null) {
initDataBindingsCustom();
updateButton();
updateUnitsLabel();
updateValueTooltip();
}
layout();
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
if (this.valueText != null && !this.valueText.isDisposed()) {
this.valueText.setEnabled(enabled);
}
if (this.unitsButton != null && !this.unitsButton.isDisposed()) {
this.unitsButton.setEnabled(enabled);
}
}
/**
* Return the string to display if no value ara avaiable.
*
* @return The string to display, should never be null.
*/
protected String getNoValueText() {
if (this.noValueText == null) {
return "";
} else {
return this.noValueText;
}
}
/**
* Creates the label that identifies the feature being displayed.
*
* @param parent The parent.
* @param labelWidth The desired label width.
* @return The Label.
*/
protected Label createFeatureLabel(Composite parent, int labelWidth) {
Label lblFeatureName = new Label(parent, SWT.NONE);
lblFeatureName.setAlignment(SWT.RIGHT);
if (labelWidth > 0) {
GridData gridData = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1);
gridData.minimumWidth = labelWidth;
gridData.widthHint = labelWidth;
lblFeatureName.setLayoutData(gridData);
} else {
lblFeatureName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, true, 1, 1));
}
lblFeatureName.setText(getLabelText());
return lblFeatureName;
}
/**
* Creates the text control that displays the value.
*
* @param parent The parent.
* @param valueWidth The desired text width.
* @return The Text.
*/
protected Text getValueText(Composite parent, int valueWidth) {
Text txtValue = new Text(this, SWT.BORDER | SWT.RIGHT);
if (valueWidth > 0) {
GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
gridData.minimumWidth = valueWidth;
gridData.widthHint = valueWidth;
txtValue.setLayoutData(gridData);
} else {
txtValue.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
}
return txtValue;
}
/**
* Creates the label that displays the units.
*
* @param parent The parent.
* @param buttonUnitsWidth The desired units label width.
* @return The Label.
*/
protected Label createUnitsLabel(Composite parent, int buttonUnitsWidth) {
Label lblUnits = new Label(parent, SWT.NONE);
if (buttonUnitsWidth > 0) {
GridData gd_unitsLabel = new GridData(SWT.LEFT, SWT.CENTER, false, true, 1, 1);
gd_unitsLabel.minimumWidth = buttonUnitsWidth;
gd_unitsLabel.widthHint = buttonUnitsWidth;
lblUnits.setLayoutData(gd_unitsLabel);
} else {
lblUnits.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
}
lblUnits.setText("Units");
return lblUnits;
}
/**
* Creates the button that display and control the units displayed.
*
* @param parent The parent.
* @param buttonUnitsWidth The desired units button width.
* @return The Button.
*/
protected Button createUnitsButton(Composite parent, int buttonUnitsWidth) {
Button btnUnits = new Button(parent, SWT.PUSH);
btnUnits.setText("Units");
if (buttonUnitsWidth > 0) {
GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1);
gridData.minimumWidth = buttonUnitsWidth;
gridData.widthHint = buttonUnitsWidth;
btnUnits.setLayoutData(gridData);
} else {
btnUnits.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
}
return btnUnits;
}
/**
* Method that can be overwritten that sets the text on the label.
*/
protected String getLabelText() {
return "";
}
/**
* Return the most specifi feature being referd to.
*
* @return The EStructuralFeature.
*/
protected EStructuralFeature getEStructuralFeature() {
EStructuralFeature feature = null;
if (this.featurePath != null) {
EStructuralFeature[] features = this.featurePath.getFeaturePath();
if (features != null && features.length > 0) {
feature = features[features.length - 1];
}
}
return feature;
}
/**
* Fomrat the name of a EStructuralFeature for display
*
* @param eStructuralFeature The EStructuralFeature.
* @return The format name of the feature.
*/
protected String getLabelFromEStructuralFeature(EStructuralFeature eStructuralFeature) {
String raw = getEStructuralFeature().getName();
String formated = raw.replaceAll("(.)([A-Z])", "$1 $2");
formated = formated.substring(0, 1).toUpperCase() + formated.substring(1);
return formated;
}
/**
* Returns whether or not the current feature is editable by the user..
*
* @return True if editable, false otherwise.
*/
protected boolean isFeatureEditable() {
if (getEStructuralFeature() == null) {
return false;
} else {
String propertyString = getAnnotationDetail(getEStructuralFeature(), "property");
if (propertyString == null) {
return true;
} else if (propertyString.contains("Editable")) {
return true;
} else if (propertyString.contains("None")) {
return false;
} else if (propertyString.contains("Readonly")) {
return false;
}
return false;
}
}
/**
* Return the value reffered to by a FeaturePath on a given EObject.
*
* @param eObject The Eobject.
* @param featurePath The FeaturePath.
* @return The current value.
*/
protected Double resolveValue(final EObject eObject, final FeaturePath featurePath) {
if (eObject != null && featurePath != null) {
EStructuralFeature[] features = featurePath.getFeaturePath();
int i = 0;
Object object = null;
EObject currentEObject = eObject;
while (i < features.length) {
EStructuralFeature currentFeature = features[i];
object = currentEObject.eGet(currentFeature);
// If we have reached the destination
if (i + 1 == features.length) {
if (object instanceof Number) {
Number value = (Number) object;
return value.doubleValue();
} else {
return null;
}
} else {
if (object != null) {
if (object instanceof EObject) {
currentEObject = (EObject) object;
}
} else {
return null;
}
}
i++;
}
return null;
} else {
return null;
}
}
/**
* Returns the string value found in the EAnnotation GenModel for a given
* ETypedElement and key.
*
* @param eTypedElement The eTypedElement.
* @param key The key of the details in the annotation.
* @return The value string found, or null if none could be extracted.
*/
protected String getAnnotationDetail(ETypedElement eTypedElement, String key) {
EAnnotation annotation = eTypedElement.getEAnnotation("http://www.eclipse.org/emf/2002/GenModel");
if (annotation != null) {
EMap<String, String> map = annotation.getDetails();
if (map != null)
return map.get(key);
}
return null;
}
/**
* Returns the native units of the feature benig displayed.
*
* @return The Unit, null if none is found.
*/
protected Unit<?> getNativeUnits() {
return ApogyCommonEMFFacade.INSTANCE.getEngineeringUnits(getEStructuralFeature());
}
/**
* Returns the units currently used for display.
*
* @return The Unit, null if none is found.
*/
protected Unit<?> getDisplayUnits() {
if (getEStructuralFeature() != null) {
return ApogyCommonEMFUIFacade.INSTANCE.getDisplayUnits(getEStructuralFeature());
} else {
return null;
}
}
/**
* Gets the DecimalFormat to use to format the displayed value.
*
* @return The decimalFormat to use.
*/
protected DecimalFormat getDecimalFormat() {
if (getEStructuralFeature() != null) {
return ApogyCommonEMFUIFacade.INSTANCE.getDisplayFormat(getEStructuralFeature());
} else {
return null;
}
}
/**
* Returns the Ranges associated with the current value being displayed.
*
* @param eTypedElement The eTypedElement.
* @param value The value.
* @return The current Ranges in which the value falls.
*/
protected Ranges getRange(ETypedElement eTypedElement, Object value) {
return ApogyCommonEMFFacade.INSTANCE.getRange(getEStructuralFeature(), value);
}
/**
* Return the text to be displayed as tooltip for the value text.
*
* @return The tootip text.
*/
protected String getToolTipDescription() {
String description = "";
if (getEStructuralFeature() != null) {
description += ApogyCommonEMFFacade.INSTANCE.getDocumentation(getEStructuralFeature());
Unit<?> nativeUnits = ApogyCommonEMFFacade.INSTANCE.getEngineeringUnits(getEStructuralFeature());
Unit<?> displayUnits = ApogyCommonEMFUIFacade.INSTANCE.getDisplayUnits(getEStructuralFeature());
if (nativeUnits != null)
description += "Native Units : " + nativeUnits.toString() + "\n";
if (displayUnits != null)
description += "Displayed Units : " + displayUnits.toString();
Number minAlarmValue = ApogyCommonEMFFacade.INSTANCE.getAlarmMinValue(getEStructuralFeature());
if (minAlarmValue != null) {
description += "\n" + "Alarm Minimum Value : ";
if (nativeUnits != null) {
if (displayUnits != null) {
description += getDecimalFormat()
.format(nativeUnits.getConverterTo(displayUnits).convert(minAlarmValue.doubleValue()))
+ " " + displayUnits.toString();
} else {
description += getDecimalFormat().format(minAlarmValue.doubleValue()) + " "
+ nativeUnits.toString();
}
} else {
description += getDecimalFormat().format(minAlarmValue.doubleValue());
}
}
Number minWarningValue = ApogyCommonEMFFacade.INSTANCE.getWarningMinValue(getEStructuralFeature());
if (minWarningValue != null) {
description += "\n" + "Warning Minimum Value : ";
if (nativeUnits != null) {
if (displayUnits != null) {
description += getDecimalFormat()
.format(nativeUnits.getConverterTo(displayUnits).convert(minWarningValue.doubleValue()))
+ " " + displayUnits.toString();
} else {
description += getDecimalFormat().format(minWarningValue.doubleValue()) + " "
+ nativeUnits.toString();
}
} else {
description += getDecimalFormat().format(minWarningValue.doubleValue());
}
}
Number maxWarningValue = ApogyCommonEMFFacade.INSTANCE.getWarningMaxValue(getEStructuralFeature());
if (maxWarningValue != null) {
description += "\n" + "Warning Maximum Value : ";
if (nativeUnits != null) {
if (displayUnits != null) {
description += getDecimalFormat()
.format(nativeUnits.getConverterTo(displayUnits).convert(maxWarningValue.doubleValue()))
+ " " + displayUnits.toString();
} else {
description += getDecimalFormat().format(maxWarningValue.doubleValue()) + " "
+ nativeUnits.toString();
}
} else {
description += getDecimalFormat().format(maxWarningValue.doubleValue());
}
}
Number maxAlarmValue = ApogyCommonEMFFacade.INSTANCE.getAlarmMaxValue(getEStructuralFeature());
if (maxAlarmValue != null) {
description += "\n" + "Alarm Maximum Value : ";
if (nativeUnits != null) {
if (displayUnits != null) {
description += getDecimalFormat()
.format(nativeUnits.getConverterTo(displayUnits).convert(maxAlarmValue.doubleValue()))
+ " " + displayUnits.toString();
} else {
description += getDecimalFormat().format(maxAlarmValue.doubleValue()) + " "
+ nativeUnits.toString();
}
} else {
description += getDecimalFormat().format(maxAlarmValue.doubleValue());
}
}
Number outsideMinValue = ApogyCommonEMFFacade.INSTANCE.getOutOfRangeMinValue(getEStructuralFeature());
if (outsideMinValue != null) {
description += "\n" + "Out Of Range Minimum Value : ";
if (nativeUnits != null) {
if (displayUnits != null) {
description += getDecimalFormat()
.format(nativeUnits.getConverterTo(displayUnits).convert(outsideMinValue.doubleValue()))
+ " " + displayUnits.toString();
} else {
description += getDecimalFormat().format(outsideMinValue.doubleValue()) + " "
+ nativeUnits.toString();
}
} else {
description += getDecimalFormat().format(outsideMinValue.doubleValue());
}
}
Number outsideMaxValue = ApogyCommonEMFFacade.INSTANCE.getOutOfRangeMaxValue(getEStructuralFeature());
if (outsideMaxValue != null) {
description += "\n" + "Out Of Range Maximum Value : ";
if (nativeUnits != null) {
if (displayUnits != null) {
description += getDecimalFormat()
.format(nativeUnits.getConverterTo(displayUnits).convert(outsideMaxValue.doubleValue()))
+ " " + displayUnits.toString();
} else {
description += getDecimalFormat().format(outsideMaxValue.doubleValue()) + " "
+ nativeUnits.toString();
}
} else {
description += getDecimalFormat().format(outsideMaxValue.doubleValue());
}
}
}
return description;
}
@SuppressWarnings("unchecked")
private void initDataBindingsCustom() {
this.bindingContext = new DataBindingContext();
/** UI Observables */ // FocusOut
IObservableValue<?> observableValueTextTextValue = WidgetProperties.text(SWT.FocusOut).observe(this.valueText);
IObservableValue<?> observableValueBackgroundTextValue = WidgetProperties.background().observe(this.valueText);
/** Value observable */
TransactionalEditingDomain editingDomain = ApogyCommonTransactionFacade.INSTANCE
.getTransactionalEditingDomain(this.eObject);
/*
* IObservableValue<?> observeTypedElementValue = editingDomain != null ?
* EMFEditProperties.value(editingDomain,
* getEStructuralFeature()).observe(eObject) :
* EMFProperties.value(getEStructuralFeature()).observe(eObject);
*/
IObservableValue<?> observeTypedElementValue = editingDomain != null
? EMFEditProperties.value(editingDomain, this.featurePath).observe(this.eObject)
: EMFProperties.value(this.featurePath).observe(this.eObject);
this.colorBinding = this.bindingContext.bindValue(observableValueBackgroundTextValue, observeTypedElementValue,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER),
new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE)
.setConverter(new Converter(String.class, Color.class) {
@Override
public Object convert(Object fromObject) {
Color color = ApogyCommonEMFUIFacade.INSTANCE
.getColorForRange(getRange(getEStructuralFeature(),
resolveValue(TypedElementSimpleUnitsComposite.this.eObject,
TypedElementSimpleUnitsComposite.this.featurePath)));
return color != null ? color : getDisplay().getSystemColor(SWT.TRANSPARENT);
}
}));
this.valueBinding = this.bindingContext.bindValue(observableValueTextTextValue, observeTypedElementValue,
getUpdateModelValueStrategy(), getUpdateTextValueStrategy());
this.valueText.setToolTipText(getToolTipDescription());
}
private UpdateValueStrategy getUpdateModelValueStrategy() {
// Check if the feature is readonly
boolean featureEditable = isFeatureEditable();
if (featureEditable) {
return new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE)
.setConverter(new Converter(String.class, getEStructuralFeature().getEType().getInstanceClass()) {
@Override
public Object convert(Object fromObject) {
if (fromObject != null && !"".equals(fromObject)) {
try {
Number number = ApogyCommonEMFUIFacade.INSTANCE.convertToNativeUnits(
Double.parseDouble((String) fromObject), getNativeUnits(),
getDisplayUnits(), getEStructuralFeature().getEType());
/**
* Format to update the text if there is rounding errors
*/
Unit<?> displayUnits = getDisplayUnits();
Unit<?> nativeUnits = getNativeUnits();
DecimalFormat format = getDecimalFormat();
if (displayUnits != null && !displayUnits.equals(nativeUnits)) {
TypedElementSimpleUnitsComposite.this.valueText
.setText(format.format(nativeUnits.getConverterTo(displayUnits)
.convert(number.doubleValue())));
} else {
TypedElementSimpleUnitsComposite.this.valueText
.setText(format.format(number.doubleValue()));
}
/** Set the new value in the right type */
EClassifier classifier = getEStructuralFeature().getEType();
if (classifier == EcorePackage.Literals.EFLOAT) {
number = number.floatValue();
} else if (classifier == EcorePackage.Literals.EBYTE) {
number = number.byteValue();
} else if (classifier == EcorePackage.Literals.ESHORT) {
number = number.shortValue();
} else if (classifier == EcorePackage.Literals.EINT) {
number = number.intValue();
} else if (classifier == EcorePackage.Literals.ELONG) {
number = number.longValue();
}
return number;
} catch (Exception e) {
Logger.error(e.getMessage(), e);
/** Error message */
MessageDialog.openError(getShell(), "Invalid Number",
"The number entered is invalid. The value will be unset.");
}
}
/** Set to the current value */
TypedElementSimpleUnitsComposite.this.valueText.setText(getFormatedValue());
return TypedElementSimpleUnitsComposite.this.eObject.eGet(getEStructuralFeature());
}
});
} else {
return new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER);
}
}
private UpdateValueStrategy getUpdateTextValueStrategy() {
return new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE)
.setConverter(new Converter(getEStructuralFeature().getEType().getInstanceClass(), String.class) {
@Override
public Object convert(Object fromObject) {
if (fromObject != null) {
String value = getFormatedValue();
return value == null ? "" : value;
}
return "";
}
});
}
/** Preference listener */
private IPropertyChangeListener getPropertyChangeListener() {
if (this.propertyChangeListener == null) {
this.propertyChangeListener = new IPropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
if (event != null && event.getProperty() != null) {
/**
* Unit of format preference event, update the value text
*/
if (event.getProperty().equals(PreferencesConstants.TYPED_ELEMENTS_UNITS_ID)
|| PreferencesConstants.isFormatPreference(event.getProperty())) {
if (TypedElementSimpleUnitsComposite.this.valueBinding != null)
TypedElementSimpleUnitsComposite.this.valueBinding.updateModelToTarget();
updateButton();
updateUnitsLabel();
updateValueTooltip();
}
/** Range preference event, update the background color */
else if (event.getProperty().equals(Ranges.UNKNOWN.getName())
|| event.getProperty().equals(Ranges.NOMINAL.getName())
|| event.getProperty().equals(Ranges.WARNING.getName())
|| event.getProperty().equals(Ranges.ALARM.getName())
|| event.getProperty().equals(Ranges.OUT_OF_RANGE.getName())) {
if (TypedElementSimpleUnitsComposite.this.colorBinding != null)
TypedElementSimpleUnitsComposite.this.colorBinding.updateModelToTarget();
}
}
}
};
}
return this.propertyChangeListener;
}
/** Updates the buttons */
private void updateButton() {
if (this.unitsButton != null && !this.unitsButton.isDisposed()) {
try {
Unit<?> units = getDisplayUnits();
if (units != null) {
this.unitsButton.setText(units.toString());
GC gc = new GC(this);
int width = (int) (gc.getFontMetrics().getLeading()
+ gc.getFontMetrics().getAverageCharacterWidth() * units.toString().length() + 20);
GridData gd_buttonUnits = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
gd_buttonUnits.widthHint = width;
gd_buttonUnits.minimumWidth = width;
this.unitsButton.setLayoutData(gd_buttonUnits);
} else {
this.unitsButton.setText("Units");
}
this.layout(true, true);
} catch (Throwable t) {
Logger.error(t.getMessage(), t);
}
}
}
private void updateValueTooltip() {
if (this.valueText != null && !this.valueText.isDisposed()) {
this.valueText.setToolTipText(getToolTipDescription());
}
}
private void updateUnitsLabel() {
if (this.unitsLabel != null && !this.unitsLabel.isDisposed()) {
Unit<?> units = getDisplayUnits();
if (units != null) {
this.unitsLabel.setText(units.toString());
GC gc = new GC(this);
int width = (int) (gc.getFontMetrics().getLeading()
+ gc.getFontMetrics().getAverageCharacterWidth() * units.toString().length() + 10);
GridData gd_buttonUnits = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
gd_buttonUnits.widthHint = width;
this.unitsLabel.setLayoutData(gd_buttonUnits);
} else {
this.unitsLabel.setText("ALLO");
}
this.unitsLabel.requestLayout();
this.requestLayout();
}
}
/**
* Gets the value formatted with the right decimalFormat and units.
*/
private String getFormatedValue() {
Double valueDouble = resolveValue(this.eObject, this.featurePath);
if (valueDouble != null) {
DecimalFormat format = getDecimalFormat();
Unit<?> displayUnits = ApogyCommonEMFUIFacade.INSTANCE.getDisplayUnits(getEStructuralFeature());
Unit<?> nativeUnits = ApogyCommonEMFFacade.INSTANCE.getEngineeringUnits(getEStructuralFeature());
if (displayUnits != null && !displayUnits.equals(nativeUnits)) {
valueDouble = nativeUnits.getConverterTo(displayUnits).convert(valueDouble);
}
return format.format(valueDouble);
} else {
return getNoValueText();
}
}
}