Skip to content

Package: NumericalControl$NumericalModelToTargetUpdateStrategy

NumericalControl$NumericalModelToTargetUpdateStrategy

nameinstructionbranchcomplexitylinemethod
NumericalControl.NumericalModelToTargetUpdateStrategy(NumericalControl)
M: 7 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
convertValue(Object)
M: 16 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2011-2013 EclipseSource Muenchen GmbH and others.
3: *
4: * All rights reserved. This program and the accompanying materials
5: * are made available under the terms of the Eclipse Public License 2.0
6: * which accompanies this distribution, and is available at
7: * https://www.eclipse.org/legal/epl-2.0/
8: *
9: * SPDX-License-Identifier: EPL-2.0
10: *
11: * Contributors:
12: * Eugen Neufeld - initial API and implementation
13: * Edgar Mueller - refactored control to respect locale settings
14: *
15: *******************************************************************************/
16: package org.eclipse.emf.ecp.edit.internal.swt.controls;
17:
18: import java.text.DecimalFormat;
19: import java.text.ParseException;
20: import java.text.ParsePosition;
21:
22: import org.eclipse.core.databinding.Binding;
23: import org.eclipse.core.databinding.observable.value.IObservableValue;
24: import org.eclipse.core.databinding.observable.value.IValueChangeListener;
25: import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
26: import org.eclipse.emf.ecp.edit.internal.swt.Activator;
27: import org.eclipse.emf.ecp.edit.spi.swt.util.ECPDialogExecutor;
28: import org.eclipse.emf.edit.command.SetCommand;
29: import org.eclipse.emfforms.spi.localization.LocalizationServiceHelper;
30: import org.eclipse.jface.databinding.swt.typed.WidgetProperties;
31: import org.eclipse.jface.dialogs.IDialogLabelKeys;
32: import org.eclipse.jface.dialogs.MessageDialog;
33: import org.eclipse.jface.resource.JFaceResources;
34: import org.eclipse.swt.SWT;
35: import org.eclipse.swt.widgets.Text;
36:
37: /**
38: * This class is used as a common class for all number controls.
39: *
40: * @author Eugen Neufeld
41: * @author emueller
42: */
43: @Deprecated
44: public class NumericalControl extends AbstractTextControl {
45:
46:         @Override
47:         protected int getTextWidgetStyle() {
48:                 return super.getTextWidgetStyle() | SWT.RIGHT;
49:         }
50:
51:         /*
52:          * (non-Javadoc)
53:          * @see org.eclipse.emf.ecp.edit.internal.swt.controls.AbstractTextControl#getTextVariantID()
54:          */
55:         @Override
56:         protected String getTextVariantID() {
57:                 return "org_eclipse_emf_ecp_control_numerical"; //$NON-NLS-1$
58:         }
59:
60:         /*
61:          * (non-Javadoc)
62:          * @see org.eclipse.emf.ecp.edit.internal.swt.controls.SingleControl#getUnsetLabelText()
63:          */
64:         @Override
65:         protected String getUnsetLabelText() {
66:                 return LocalizationServiceHelper.getString(getClass(),
67:                         DepricatedControlMessageKeys.NumericalControl_NoNumberClickToSetNumber);
68:         }
69:
70:         /*
71:          * (non-Javadoc)
72:          * @see org.eclipse.emf.ecp.edit.internal.swt.controls.SingleControl#getUnsetButtonTooltip()
73:          */
74:         @Override
75:         protected String getUnsetButtonTooltip() {
76:                 return LocalizationServiceHelper.getString(getClass(),
77:                         DepricatedControlMessageKeys.NumericalControl_UnsetNumber);
78:         }
79:
80:         @Override
81:         protected void customizeText(Text text) {
82:                 super.customizeText(text);
83:                 text.setMessage(getFormatText());
84:         }
85:
86:         /*
87:          * (non-Javadoc)
88:          * @see org.eclipse.emf.ecp.edit.internal.swt.controls.AbstractTextControl#bindValue()
89:          */
90:         @Override
91:         public Binding bindValue() {
92:                 // TODO: FocusOut doesn't seem to fire in case the same invalid text is entered twice
93:                 final IObservableValue value = WidgetProperties.text(SWT.FocusOut).observe(getText());
94:                 final NumericalTargetToModelUpdateStrategy targetToModelStrategy = new NumericalTargetToModelUpdateStrategy();
95:                 final NumericalModelToTargetUpdateStrategy modelToTargetStrategy = new NumericalModelToTargetUpdateStrategy();
96:                 final Binding binding = getDataBindingContext().bindValue(value, getModelValue(), targetToModelStrategy,
97:                         modelToTargetStrategy);
98:
99:                 createTooltipBinding(targetToModelStrategy, modelToTargetStrategy);
100:
101:                 if (isEmbedded()) {
102:                         // focus out is not fired if control is embedded;
103:                         // use value change listener to get same behavior for control
104:                         value.addValueChangeListener(new IValueChangeListener() {
105:                                 @Override
106:                                 public void handleValueChange(ValueChangeEvent event) {
107:                                         final Object newValue = event.diff.getNewValue();
108:                                         final DecimalFormat format = NumericalHelper.setupFormat(getLocale(),
109:                                                 getInstanceClass());
110:                                         try {
111:                                                 final Number number = format.parse((String) newValue);
112:                                                 value.setValue(format.format(number));
113:                                                 binding.updateTargetToModel();
114:                                         } catch (final ParseException ex) {
115:                                                 targetToModelStrategy.revertToOldValue(value);
116:                                         }
117:                                 }
118:                         });
119:                 }
120:
121:                 return binding;
122:         }
123:
124:         private Class<?> getInstanceClass() {
125:                 return getFirstStructuralFeature().getEType().getInstanceClass();
126:         }
127:
128:         private String getFormatText() {
129:
130:                 if (NumericalHelper.isInteger(getInstanceClass())) {
131:                         return LocalizationServiceHelper.getString(getClass(),
132:                                 DepricatedControlMessageKeys.NumericalControl_FormatNumerical);
133:                 } else if (NumericalHelper.isDouble(getInstanceClass())) {
134:                         return LocalizationServiceHelper.getString(getClass(),
135:                                 DepricatedControlMessageKeys.NumericalControl_FormatNumericalDecimal);
136:                 }
137:
138:                 return ""; //$NON-NLS-1$
139:         }
140:
141:         /**
142:          * Converts the numerical value from the model to the target. Locale settings are respected,
143:          * i.e. formatting is performed according to the current locale.
144:          */
145:         private class NumericalModelToTargetUpdateStrategy extends ModelToTargetUpdateStrategy {
146:
147:                 @Override
148:                 public Object convertValue(Object value) {
149:•                        if (value == null) {
150:                                 return ""; //$NON-NLS-1$
151:                         }
152:                         final DecimalFormat format = NumericalHelper.setupFormat(getLocale(),
153:                                 getInstanceClass());
154:                         return format.format(value);
155:                 }
156:         }
157:
158:         /**
159:          * More specific target to model update strategy that convert the string
160:          * in the text field to a number. If the string is a invalid number,
161:          * for instance because of the current locale, the value is reset to
162:          * the last valid value found in the mode.
163:          */
164:         private class NumericalTargetToModelUpdateStrategy extends TargetToModelUpdateStrategy {
165:
166:                 private final DecimalFormat format;
167:
168:                 NumericalTargetToModelUpdateStrategy() {
169:                         super();
170:                         format = NumericalHelper.setupFormat(getLocale(), getInstanceClass());
171:
172:                 }
173:
174:                 @Override
175:                 protected Object convertValue(final Object value) {
176:
177:                         try {
178:                                 Number number = null;
179:                                 if (value == null) {
180:                                         number = NumericalHelper.getDefaultValue(getInstanceClass());
181:                                 } else {
182:                                         final ParsePosition pp = new ParsePosition(0);
183:                                         number = format.parse((String) value, pp);
184:                                         if (pp.getErrorIndex() != -1 || pp.getIndex() != ((String) value).length()) {
185:                                                 return revertToOldValue(value);
186:                                         }
187:                                         if (NumericalHelper.isInteger(getInstanceClass())) {
188:                                                 boolean maxValue = false;
189:                                                 final Class<?> instanceClass = getInstanceClass();
190:                                                 String formatedValue = ""; //$NON-NLS-1$
191:                                                 if (isOfClass(Integer.class, instanceClass) && Integer.MAX_VALUE == number.intValue()) {
192:                                                         maxValue = true;
193:                                                         formatedValue = format.format(Integer.MAX_VALUE);
194:                                                 } else if (isOfClass(Long.class, instanceClass) && Long.MAX_VALUE == number.longValue()) {
195:                                                         maxValue = true;
196:                                                         formatedValue = format.format(Long.MAX_VALUE);
197:                                                 }
198:
199:                                                 if (maxValue) {
200:                                                         getText().setText(formatedValue);
201:                                                         return NumericalHelper.numberToInstanceClass(number, getInstanceClass());
202:                                                 }
203:                                         }
204:                                 }
205:                                 String formatedNumber = ""; //$NON-NLS-1$
206:                                 if (number != null) {
207:                                         formatedNumber = format.format(number);
208:                                 }
209:                                 // if (number.toString().contains("E") //$NON-NLS-1$
210:                                 // || ((String) value).matches("0*" + formatedNumber + "\\" //$NON-NLS-1$ //$NON-NLS-2$
211:                                 // + format.getDecimalFormatSymbols().getDecimalSeparator() + "?0*")) { //$NON-NLS-1$
212:                                 //
213:                                 // }
214:                                 // return revertToOldValue(value);
215:                                 getText().setText(formatedNumber);
216:                                 if (formatedNumber.length() == 0) {
217:                                         return null;
218:                                 }
219:                                 return NumericalHelper.numberToInstanceClass(format.parse(formatedNumber), getInstanceClass());
220:                         } catch (final ParseException ex) {
221:                                 return revertToOldValue(value);
222:                         }
223:                 }
224:
225:                 private <T extends Number> boolean isOfClass(Class<T> clazz, Class<?> toCheck) {
226:                         try {
227:                                 return clazz.isAssignableFrom(toCheck)
228:                                         || clazz.getField("TYPE").get(null).equals(toCheck); //$NON-NLS-1$
229:                         } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException ex) {
230:                                 Activator.logException(ex);
231:                                 return false;
232:                         }
233:                 }
234:
235:                 private Object revertToOldValue(final Object value) {
236:
237:                         if (getFirstStructuralFeature().getDefaultValue() == null && (value == null || value.equals(""))) { //$NON-NLS-1$
238:                                 return null;
239:                         }
240:
241:                         final Object result = getModelValue().getValue();
242:
243:                         final MessageDialog messageDialog = new MessageDialog(getText().getShell(),
244:                                 LocalizationServiceHelper.getString(getClass(),
245:                                         DepricatedControlMessageKeys.NumericalControl_InvalidNumber),
246:                                 null,
247:                                 LocalizationServiceHelper.getString(getClass(),
248:                                         DepricatedControlMessageKeys.NumericalControl_InvalidNumberWillBeUnset),
249:                                 MessageDialog.ERROR,
250:                                 new String[] { JFaceResources.getString(IDialogLabelKeys.OK_LABEL_KEY) }, 0);
251:
252:                         new ECPDialogExecutor(messageDialog) {
253:                                 @Override
254:                                 public void handleResult(int codeResult) {
255:
256:                                 }
257:                         }.execute();
258:
259:                         if (result == null) {
260:                                 getText().setText(""); //$NON-NLS-1$
261:                         } else {
262:                                 getDataBindingContext().updateTargets();
263:                         }
264:
265:                         if (getFirstStructuralFeature().isUnsettable() && result == null) {
266:                                 showUnsetLabel();
267:                                 return SetCommand.UNSET_VALUE;
268:                         }
269:                         return result;
270:                 }
271:         }
272:
273: }