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