Skip to content

Package: TypedElementBoundsRenderer$6

TypedElementBoundsRenderer$6

nameinstructionbranchcomplexitylinemethod
run()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
{...}
M: 0 C: 6
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2011-2019 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: * Clemens Elflein - initial API and implementation
13: * Alexandra Buzila - refactoring
14: * Christian W. Damus - bug 548592
15: ******************************************************************************/
16: package org.eclipse.emfforms.internal.editor.ecore.controls;
17:
18: import java.util.ArrayList;
19: import java.util.List;
20:
21: import javax.inject.Inject;
22:
23: import org.eclipse.core.databinding.DataBindingContext;
24: import org.eclipse.core.databinding.UpdateValueStrategy;
25: import org.eclipse.core.databinding.observable.value.IObservableValue;
26: import org.eclipse.core.runtime.IStatus;
27: import org.eclipse.core.runtime.Status;
28: import org.eclipse.emf.databinding.edit.EMFEditObservables;
29: import org.eclipse.emf.ecore.EObject;
30: import org.eclipse.emf.ecore.EStructuralFeature;
31: import org.eclipse.emf.ecore.EcorePackage;
32: import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
33: import org.eclipse.emf.ecp.view.spi.core.swt.AbstractControlSWTRenderer;
34: import org.eclipse.emf.ecp.view.spi.model.LabelAlignment;
35: import org.eclipse.emf.ecp.view.spi.model.VControl;
36: import org.eclipse.emf.ecp.view.spi.renderer.NoPropertyDescriptorFoundExeption;
37: import org.eclipse.emf.ecp.view.spi.renderer.NoRendererFoundException;
38: import org.eclipse.emf.ecp.view.template.model.VTViewTemplateProvider;
39: import org.eclipse.emfforms.spi.common.report.ReportService;
40: import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedException;
41: import org.eclipse.emfforms.spi.core.services.databinding.EMFFormsDatabinding;
42: import org.eclipse.emfforms.spi.core.services.label.EMFFormsLabelProvider;
43: import org.eclipse.emfforms.spi.localization.LocalizationServiceHelper;
44: import org.eclipse.emfforms.spi.swt.core.layout.GridDescriptionFactory;
45: import org.eclipse.emfforms.spi.swt.core.layout.SWTGridCell;
46: import org.eclipse.emfforms.spi.swt.core.layout.SWTGridDescription;
47: import org.eclipse.jface.databinding.swt.ISWTObservableValue;
48: import org.eclipse.jface.databinding.swt.typed.WidgetProperties;
49: import org.eclipse.jface.layout.GridDataFactory;
50: import org.eclipse.jface.layout.GridLayoutFactory;
51: import org.eclipse.swt.SWT;
52: import org.eclipse.swt.graphics.Color;
53: import org.eclipse.swt.layout.GridData;
54: import org.eclipse.swt.widgets.Button;
55: import org.eclipse.swt.widgets.Composite;
56: import org.eclipse.swt.widgets.Control;
57: import org.eclipse.swt.widgets.Display;
58: import org.eclipse.swt.widgets.Label;
59: import org.eclipse.swt.widgets.Spinner;
60:
61: /**
62: *
63: * The Renderer allowing the user to test the bounds with two Combos.
64: *
65: * @author Clemens Elflein
66: */
67: public class TypedElementBoundsRenderer extends AbstractControlSWTRenderer<VControl> {
68:
69:         private Spinner lowerBound;
70:         private Spinner upperBound;
71:         private Button unbounded;
72:
73:         /**
74:          * Default constructor.
75:          *
76:          * @param vElement the view model element to be rendered
77:          * @param viewContext the view context
78:          * @param emfFormsDatabinding The {@link EMFFormsDatabinding}
79:          * @param emfFormsLabelProvider The {@link EMFFormsLabelProvider}
80:          * @param reportService The {@link ReportService}
81:          * @param vtViewTemplateProvider The {@link VTViewTemplateProvider}
82:          */
83:         @Inject
84:         public TypedElementBoundsRenderer(VControl vElement, ViewModelContext viewContext, ReportService reportService,
85:                 EMFFormsDatabinding emfFormsDatabinding, EMFFormsLabelProvider emfFormsLabelProvider,
86:                 VTViewTemplateProvider vtViewTemplateProvider) {
87:                 super(vElement, viewContext, reportService, emfFormsDatabinding, emfFormsLabelProvider, vtViewTemplateProvider);
88:         }
89:
90:         private SWTGridDescription rendererGridDescription;
91:
92:         @Override
93:         public final SWTGridDescription getGridDescription(SWTGridDescription gridDescription) {
94:                 if (rendererGridDescription == null) {
95:                         final boolean showLabel = getVElement().getLabelAlignment() != LabelAlignment.NONE;
96:                         final int columns = showLabel ? 3 : 2;
97:
98:                         rendererGridDescription = GridDescriptionFactory.INSTANCE.createEmptyGridDescription();
99:                         rendererGridDescription.setRows(1);
100:                         rendererGridDescription.setColumns(columns);
101:
102:                         final List<SWTGridCell> grid = new ArrayList<SWTGridCell>();
103:
104:                         if (columns == 3) {
105:                                 final SWTGridCell labelCell = createLabelCell(grid.size());
106:                                 grid.add(labelCell);
107:                         }
108:
109:                         final SWTGridCell validationCell = createValidationCell(grid.size());
110:                         grid.add(validationCell);
111:
112:                         final SWTGridCell controlCel = createControlCell(grid.size());
113:                         grid.add(controlCel);
114:
115:                         rendererGridDescription.setGrid(grid);
116:                 }
117:                 return rendererGridDescription;
118:         }
119:
120:         private SWTGridCell createLabelCell(int column) {
121:                 final SWTGridCell labelCell = new SWTGridCell(0, column, this);
122:                 labelCell.setHorizontalGrab(false);
123:                 labelCell.setVerticalGrab(false);
124:                 labelCell.setHorizontalFill(false);
125:                 labelCell.setHorizontalAlignment(SWTGridCell.Alignment.BEGINNING);
126:                 labelCell.setVerticalFill(false);
127:                 labelCell.setVerticalAlignment(SWTGridCell.Alignment.CENTER);
128:                 labelCell.setRenderer(this);
129:                 return labelCell;
130:         }
131:
132:         private SWTGridCell createValidationCell(int column) {
133:                 final SWTGridCell validationCell = new SWTGridCell(0, column, this);
134:                 validationCell.setHorizontalGrab(false);
135:                 validationCell.setVerticalGrab(false);
136:                 validationCell.setHorizontalFill(false);
137:                 validationCell.setHorizontalAlignment(SWTGridCell.Alignment.CENTER);
138:                 validationCell.setVerticalFill(false);
139:                 validationCell.setVerticalAlignment(SWTGridCell.Alignment.CENTER);
140:                 validationCell.setRenderer(this);
141:                 validationCell.setPreferredSize(16, 17);
142:                 return validationCell;
143:         }
144:
145:         private SWTGridCell createControlCell(int column) {
146:                 final SWTGridCell controlCell = new SWTGridCell(0, column, this);
147:                 controlCell.setHorizontalGrab(true);
148:                 controlCell.setVerticalGrab(false);
149:                 controlCell.setHorizontalFill(true);
150:                 controlCell.setVerticalFill(false);
151:                 controlCell.setVerticalAlignment(SWTGridCell.Alignment.CENTER);
152:                 controlCell.setRenderer(this);
153:                 return controlCell;
154:         }
155:
156:         @Override
157:         protected final Control renderControl(SWTGridCell gridCell, Composite parent)
158:                 throws NoRendererFoundException, NoPropertyDescriptorFoundExeption {
159:                 int controlIndex = gridCell.getColumn();
160:                 if (getVElement().getLabelAlignment() == LabelAlignment.NONE) {
161:                         controlIndex++;
162:                 }
163:                 switch (controlIndex) {
164:                 case 0:
165:                         return createBoundsLabel(parent);
166:                 case 1:
167:                         return createValidationIcon(parent);
168:                 case 2:
169:                         return createControl(parent);
170:                 default:
171:                         throw new IllegalArgumentException(
172:                                 String
173:                                         .format(
174:                                                 "The provided SWTGridCell (%1$s) cannot be used by this (%2$s) renderer.", gridCell.toString(), //$NON-NLS-1$
175:                                                 toString()));
176:                 }
177:         }
178:
179:         private Control createBoundsLabel(Composite parent) {
180:                 final Label label = new Label(parent, SWT.NONE);
181:                 label.setData(CUSTOM_VARIANT, "org_eclipse_emf_ecp_control_label"); //$NON-NLS-1$
182:                 label.setText(getLocalizedString(Messages.TypedElementBoundsRenderer_Bounds));
183:                 return label;
184:         }
185:
186:         private Control createControl(Composite parent) {
187:                 final Composite main = new Composite(parent, SWT.NONE);
188:                 GridLayoutFactory.fillDefaults().numColumns(3).applyTo(main);
189:                 GridDataFactory.fillDefaults().grab(true, false)
190:                         .align(SWT.FILL, SWT.BEGINNING).applyTo(main);
191:
192:                 lowerBound = new Spinner(main, SWT.BORDER);
193:                 lowerBound.setMaximum(Integer.MAX_VALUE);
194:                 lowerBound.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, true));
195:
196:                 upperBound = new Spinner(main, SWT.BORDER);
197:                 upperBound.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, true));
198:                 upperBound.setMinimum(-1);
199:                 upperBound.setMaximum(Integer.MAX_VALUE);
200:
201:                 unbounded = new Button(main, SWT.CHECK);
202:                 unbounded.setText(getLocalizedString(Messages.TypedElementBoundsRenderer_Unbounded));
203:
204:                 createDataBindings(lowerBound, upperBound, unbounded);
205:
206:                 applyValidation();
207:                 return main;
208:         }
209:
210:         private String getLocalizedString(String string) {
211:                 return LocalizationServiceHelper.getString(TypedElementBoundsRenderer.class, string);
212:         }
213:
214:         private void createDataBindings(final Spinner lowerBound, final Spinner upperBound, Button unbounded) {
215:                 final EObject domainObject = getViewModelContext().getDomainModel();
216:                 final DataBindingContext dbc = getDataBindingContext();
217:
218:                 final ISWTObservableValue lowerBoundSelectionTargetValue = WidgetProperties.spinnerSelection()
219:                         .observe(lowerBound);
220:                 final IObservableValue lowerBoundModelValue = EMFEditObservables.observeValue(getEditingDomain(domainObject),
221:                         domainObject, EcorePackage.eINSTANCE.getETypedElement_LowerBound());
222:                 dbc.bindValue(lowerBoundSelectionTargetValue, lowerBoundModelValue);
223:
224:                 final IObservableValue upperBoundModelValue = EMFEditObservables.observeValue(getEditingDomain(domainObject),
225:                         domainObject, EcorePackage.eINSTANCE.getETypedElement_UpperBound());
226:                 final ISWTObservableValue upperBoundSelectionTargetValue = WidgetProperties.spinnerSelection()
227:                         .observe(upperBound);
228:                 dbc.bindValue(upperBoundSelectionTargetValue, upperBoundModelValue);
229:
230:                 bindUpperAndLowerBounds(dbc, lowerBoundModelValue, upperBoundModelValue);
231:
232:                 /* Disable the upperBound spinner when it's value is set to -1 */
233:                 final ISWTObservableValue upperBoundEnabledTargetValue = WidgetProperties.enabled().observe(upperBound);
234:                 dbc.bindValue(upperBoundEnabledTargetValue, upperBoundModelValue, null,
235:                         new UpdateValueStrategy() {
236:                                 @Override
237:                                 public Object convert(Object value) {
238:                                         // model to target
239:                                         if (!Integer.class.isInstance(value)) {
240:                                                 return null;
241:                                         }
242:                                         return (Integer) value != -1;
243:                                 }
244:                         });
245:
246:                 /* The unbounded checkbox is selected, when the upperBound value is -1 (and vice versa) */
247:                 final ISWTObservableValue unboundedSelectionTargetValue = WidgetProperties.buttonSelection().observe(unbounded);
248:                 dbc.bindValue(unboundedSelectionTargetValue, upperBoundModelValue,
249:                         new UpdateValueStrategy() {
250:                                 @Override
251:                                 public Object convert(Object value) {
252:                                         // target to model
253:                                         final Boolean unbounded = (Boolean) value;
254:                                         if (!unbounded) {
255:                                                 return Math.max(1, lowerBound.getSelection());
256:                                         }
257:                                         return -1;
258:                                 }
259:                         }, new UpdateValueStrategy() {
260:                                 @Override
261:                                 public Object convert(Object value) {
262:                                         // model to target
263:                                         if (!Integer.class.isInstance(value)) {
264:                                                 return null;
265:                                         }
266:                                         return (Integer) value == -1;
267:                                 }
268:                         });
269:         }
270:
271:         /**
272:          * Make sure that the upperBound cannot be lower than the lowerBound and that the lowerBound cannot be higher
273:          * than the upperBound.
274:          */
275:         private void bindUpperAndLowerBounds(final DataBindingContext dbc, final IObservableValue lowerBoundModelValue,
276:                 final IObservableValue upperBoundModelValue) {
277:                 dbc.bindValue(upperBoundModelValue, lowerBoundModelValue,
278:                         new UpdateValueStrategy() {
279:                                 @Override
280:                                 public Object convert(Object value) {
281:                                         // upper value to lower value
282:                                         if (!Integer.class.isInstance(value)) {
283:                                                 return null;
284:                                         }
285:                                         final Integer upperValue = (Integer) value;
286:                                         final Integer lowerValue = (Integer) lowerBoundModelValue.getValue();
287:                                         if (upperValue < lowerValue && upperValue != -1) {
288:                                                 return upperValue;
289:                                         }
290:                                         return lowerValue;
291:                                 }
292:
293:                                 @Override
294:                                 protected IStatus doSet(IObservableValue observableValue, Object value) {
295:                                         if (observableValue.getValue().equals(value)) {
296:                                                 return Status.OK_STATUS;
297:                                         }
298:                                         return super.doSet(observableValue, value);
299:                                 }
300:                         }, new UpdateValueStrategy() {
301:                                 @Override
302:                                 public Object convert(Object value) {
303:                                         // lower value to upper value
304:                                         if (!Integer.class.isInstance(value)) {
305:                                                 return null;
306:                                         }
307:                                         final Integer lowerValue = (Integer) value;
308:                                         final Integer upperValue = (Integer) upperBoundModelValue.getValue();
309:                                         if (upperValue >= 0 && upperValue < lowerValue) {
310:                                                 return lowerValue;
311:                                         }
312:                                         return upperValue;
313:                                 }
314:
315:                                 @Override
316:                                 protected IStatus doSet(IObservableValue observableValue, Object value) {
317:                                         if (observableValue.getValue().equals(value)) {
318:                                                 return Status.OK_STATUS;
319:                                         }
320:                                         return super.doSet(observableValue, value);
321:                                 }
322:                         });
323:         }
324:
325:         private void setValidationColor(Control control, Color validationColor) {
326:                 control.setBackground(validationColor);
327:         }
328:
329:         @Override
330:         protected final void applyValidation() {
331:                 Display.getDefault().asyncExec(new Runnable() {
332:
333:                         @Override
334:                         public void run() {
335:                                 applyInnerValidation();
336:                         }
337:                 });
338:         }
339:
340:         private void applyInnerValidation() {
341:                 Label validationIcon;
342:                 Control editControl;
343:                 switch (getControls().size()) {
344:                 case 2:
345:                         validationIcon = Label.class.cast(getControls().get(
346:                                 new SWTGridCell(0, 0, TypedElementBoundsRenderer.this)));
347:                         editControl = getControls().get(new SWTGridCell(0, 1, TypedElementBoundsRenderer.this));
348:                         break;
349:                 case 3:
350:                         validationIcon = Label.class.cast(getControls().get(
351:                                 new SWTGridCell(0, 1, TypedElementBoundsRenderer.this)));
352:                         editControl = getControls().get(new SWTGridCell(0, 2, TypedElementBoundsRenderer.this));
353:                         break;
354:                 default: // TODO log error ;
355:                         return;
356:                 }
357:                 // triggered due to another validation rule before this control is rendered
358:                 if (validationIcon == null || editControl == null) {
359:                         return;
360:                 }
361:                 // validation rule triggered after the control was disposed
362:                 if (validationIcon.isDisposed()) {
363:                         return;
364:                 }
365:                 // no diagnostic set
366:                 if (getVElement().getDiagnostic() == null) {
367:                         return;
368:                 }
369:
370:                 validationIcon.setImage(getValidationIcon());
371:                 validationIcon.setToolTipText(getVElement().getDiagnostic().getMessage());
372:
373:                 setValidationColor(editControl, getValidationBackgroundColor());
374:         }
375:
376:         /**
377:          * {@inheritDoc}
378:          *
379:          * @see org.eclipse.emf.ecp.view.spi.core.swt.AbstractControlSWTRenderer#rootDomainModelChanged()
380:          */
381:         @Override
382:         protected void rootDomainModelChanged() throws DatabindingFailedException {
383:                 // TODO change implementation to use databinding
384:         }
385:
386:         /**
387:          * Reveal the given {@code feature} in my controls.
388:          *
389:          * @param feature the feature to reveal (either the upper or the lower bound)
390:          *
391:          * @since 1.22
392:          */
393:         public void reveal(EStructuralFeature feature) {
394:                 if (feature == EcorePackage.Literals.ETYPED_ELEMENT__UPPER_BOUND) {
395:                         if (upperBound != null && upperBound.isEnabled()) {
396:                                 scrollToReveal(upperBound);
397:                         } else if (unbounded != null && unbounded.isEnabled()) {
398:                                 scrollToReveal(unbounded);
399:                         }
400:                 } else if (feature == EcorePackage.Literals.ETYPED_ELEMENT__LOWER_BOUND) {
401:                         if (lowerBound != null && lowerBound.isEnabled()) {
402:                                 scrollToReveal(lowerBound);
403:                         }
404:                 }
405:         }
406:
407: }