Skip to content

Package: LinkControlSWTRenderer$9$1

LinkControlSWTRenderer$9$1

nameinstructionbranchcomplexitylinemethod
run()
M: 11 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
{...}
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2011-2021 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: * Alexandra Buzila - initial API and implementation
13: * Christian W. Damus - bug 548592
14: ******************************************************************************/
15: package org.eclipse.emf.ecp.view.internal.core.swt.renderer;
16:
17: import javax.inject.Inject;
18:
19: import org.eclipse.core.databinding.Binding;
20: import org.eclipse.core.databinding.UpdateValueStrategy;
21: import org.eclipse.core.databinding.observable.IObserving;
22: import org.eclipse.core.databinding.observable.value.IObservableValue;
23: import org.eclipse.emf.common.command.Command;
24: import org.eclipse.emf.common.notify.AdapterFactory;
25: import org.eclipse.emf.common.notify.Notification;
26: import org.eclipse.emf.ecore.EObject;
27: import org.eclipse.emf.ecore.EReference;
28: import org.eclipse.emf.ecore.EStructuralFeature;
29: import org.eclipse.emf.ecp.edit.spi.ReferenceService;
30: import org.eclipse.emf.ecp.edit.spi.util.ECPModelElementChangeListener;
31: import org.eclipse.emf.ecp.view.internal.core.swt.MessageKeys;
32: import org.eclipse.emf.ecp.view.model.common.edit.provider.CustomReflectiveItemProviderAdapterFactory;
33: import org.eclipse.emf.ecp.view.model.common.util.RendererUtil;
34: import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
35: import org.eclipse.emf.ecp.view.spi.core.swt.SimpleControlSWTControlSWTRenderer;
36: import org.eclipse.emf.ecp.view.spi.model.VControl;
37: import org.eclipse.emf.ecp.view.spi.util.swt.ImageRegistryService;
38: import org.eclipse.emf.ecp.view.template.model.VTViewTemplateProvider;
39: import org.eclipse.emf.ecp.view.template.style.reference.model.VTReferenceFactory;
40: import org.eclipse.emf.ecp.view.template.style.reference.model.VTReferenceStyleProperty;
41: import org.eclipse.emf.edit.command.SetCommand;
42: import org.eclipse.emf.edit.domain.EditingDomain;
43: import org.eclipse.emf.edit.provider.AdapterFactoryItemDelegator;
44: import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
45: import org.eclipse.emfforms.spi.common.report.AbstractReport;
46: import org.eclipse.emfforms.spi.common.report.ReportService;
47: import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedException;
48: import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedReport;
49: import org.eclipse.emfforms.spi.core.services.databinding.EMFFormsDatabinding;
50: import org.eclipse.emfforms.spi.core.services.editsupport.EMFFormsEditSupport;
51: import org.eclipse.emfforms.spi.core.services.label.EMFFormsLabelProvider;
52: import org.eclipse.emfforms.spi.core.services.label.NoLabelFoundException;
53: import org.eclipse.emfforms.spi.localization.EMFFormsLocalizationService;
54: import org.eclipse.jface.databinding.swt.typed.WidgetProperties;
55: import org.eclipse.jface.dialogs.MessageDialog;
56: import org.eclipse.jface.layout.GridDataFactory;
57: import org.eclipse.jface.layout.GridLayoutFactory;
58: import org.eclipse.jface.window.Window;
59: import org.eclipse.swt.SWT;
60: import org.eclipse.swt.custom.StackLayout;
61: import org.eclipse.swt.events.SelectionAdapter;
62: import org.eclipse.swt.events.SelectionEvent;
63: import org.eclipse.swt.graphics.Image;
64: import org.eclipse.swt.layout.GridData;
65: import org.eclipse.swt.widgets.Button;
66: import org.eclipse.swt.widgets.Composite;
67: import org.eclipse.swt.widgets.Control;
68: import org.eclipse.swt.widgets.Display;
69: import org.eclipse.swt.widgets.Label;
70: import org.eclipse.swt.widgets.Link;
71: import org.osgi.framework.Bundle;
72: import org.osgi.framework.FrameworkUtil;
73:
74: /**
75: * SWT Renderer for link controls.
76: *
77: * @author Alexandra Buzila
78: *
79: */
80: public class LinkControlSWTRenderer extends SimpleControlSWTControlSWTRenderer {
81:
82:         private Composite mainComposite;
83:         private StackLayout stackLayout;
84:         private Label imageHyperlink;
85:         private Composite linkComposite;
86:         private Link hyperlink;
87:         private final EMFFormsLocalizationService localizationService;
88:         private Button newReferenceBtn;
89:         private Button addReferenceBtn;
90:         private Button deleteReferenceButton;
91:         private Label unsetLabel;
92:         private ReferenceService referenceService;
93:         private final ImageRegistryService imageRegistryService;
94:         private final EMFFormsLabelProvider emfFormsLabelProvider;
95:         private ECPModelElementChangeListener modelElementChangeListener;
96:         private ComposedAdapterFactory composedAdapterFactory;
97:         private AdapterFactoryItemDelegator adapterFactoryItemDelegator;
98:
99:         /**
100:          * @param vElement the element to render
101:          * @param viewContext the view model context
102:          * @param reportService the report service
103:          * @param emfFormsDatabinding the data binding service
104:          * @param emfFormsLabelProvider the label provider
105:          * @param vtViewTemplateProvider the view template provider
106:          * @param localizationService the localization service
107:          * @param imageRegistryService the image registry service
108:          * @param emfFormsEditSupport the EMFFormsEditSupport
109:          *
110:          * @deprecated with 1.22
111:          */
112:         @Deprecated
113:         @Inject
114:         // CHECKSTYLE.OFF: ParameterNumber
115:         public LinkControlSWTRenderer(VControl vElement, ViewModelContext viewContext, ReportService reportService,
116:                 EMFFormsDatabinding emfFormsDatabinding, EMFFormsLabelProvider emfFormsLabelProvider,
117:                 VTViewTemplateProvider vtViewTemplateProvider, EMFFormsLocalizationService localizationService,
118:                 ImageRegistryService imageRegistryService, EMFFormsEditSupport emfFormsEditSupport) {
119:                 // CHECKSTYLE.ON: ParameterNumber
120:                 this(vElement, viewContext, reportService, emfFormsDatabinding, emfFormsLabelProvider, vtViewTemplateProvider,
121:                         localizationService, imageRegistryService);
122:         }
123:
124:         /**
125:          * @param vElement the element to render
126:          * @param viewContext the view model context
127:          * @param reportService the report service
128:          * @param emfFormsDatabinding the data binding service
129:          * @param emfFormsLabelProvider the label provider
130:          * @param vtViewTemplateProvider the view template provider
131:          * @param localizationService the localization service
132:          * @param imageRegistryService the image registry service
133:          */
134:         @Inject
135:         // CHECKSTYLE.OFF: ParameterNumber
136:         public LinkControlSWTRenderer(VControl vElement, ViewModelContext viewContext, ReportService reportService,
137:                 EMFFormsDatabinding emfFormsDatabinding, EMFFormsLabelProvider emfFormsLabelProvider,
138:                 VTViewTemplateProvider vtViewTemplateProvider, EMFFormsLocalizationService localizationService,
139:                 ImageRegistryService imageRegistryService) {
140:                 // CHECKSTYLE.ON: ParameterNumber
141:                 super(vElement, viewContext, reportService, emfFormsDatabinding, emfFormsLabelProvider, vtViewTemplateProvider);
142:                 this.localizationService = localizationService;
143:                 this.imageRegistryService = imageRegistryService;
144:                 this.emfFormsLabelProvider = emfFormsLabelProvider;
145:         }
146:
147:         @Override
148:         protected Binding[] createBindings(Control control) throws DatabindingFailedException {
149:
150:                 final IObservableValue value = WidgetProperties.text().observe(hyperlink);
151:                 final Binding binding = getDataBindingContext().bindValue(value, getModelValue(),
152:                         withPreSetValidation(createValueExtractingUpdateStrategy()),
153:                         new UpdateValueStrategy() {
154:                                 @Override
155:                                 public Object convert(Object value) {
156:                                         updateChangeListener((EObject) value);
157:                                         return "<a>" + getText(value) + "</a>"; //$NON-NLS-1$ //$NON-NLS-2$
158:                                 }
159:                         });
160:
161:                 final IObservableValue tooltipValue = WidgetProperties.tooltipText().observe(hyperlink);
162:                 final Binding tooltipBinding = getDataBindingContext().bindValue(tooltipValue, getModelValue(),
163:                         withPreSetValidation(createValueExtractingUpdateStrategy()),
164:                         new UpdateValueStrategy() {
165:                                 @Override
166:                                 public Object convert(Object value) {
167:                                         return getText(value);
168:                                 }
169:                         });
170:
171:                 final IObservableValue imageValue = WidgetProperties.image().observe(imageHyperlink);
172:                 final Binding imageBinding = getDataBindingContext().bindValue(imageValue, getModelValue(),
173:                         withPreSetValidation(new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER)),
174:                         new UpdateValueStrategy() {
175:                                 @Override
176:                                 public Object convert(Object value) {
177:                                         return getImage(value);
178:                                 }
179:                         });
180:
181:                 final IObservableValue deleteButtonEnablement = WidgetProperties.enabled().observe(deleteReferenceButton);
182:                 final Binding deleteBinding = getDataBindingContext().bindValue(deleteButtonEnablement, getModelValue(),
183:                         withPreSetValidation(createValueExtractingUpdateStrategy()),
184:                         new UpdateValueStrategy() {
185:                                 @Override
186:                                 public Object convert(Object value) {
187:                                         return value != null;
188:                                 }
189:                         });
190:
191:                 return new Binding[] { binding, tooltipBinding, imageBinding, deleteBinding };
192:         }
193:
194:         private UpdateValueStrategy createValueExtractingUpdateStrategy() {
195:                 return new UpdateValueStrategy() {
196:                         @Override
197:                         public Object convert(Object value) {
198:                                 try {
199:                                         return getModelValue().getValue();
200:                                 } catch (final DatabindingFailedException ex) {
201:                                         getReportService().report(new DatabindingFailedReport(ex));
202:                                 }
203:                                 return value;
204:                         }
205:                 };
206:         }
207:
208:         @Override
209:         protected Control createSWTControl(Composite parent) throws DatabindingFailedException {
210:                 final IObservableValue observableValue = getEMFFormsDatabinding()
211:                         .getObservableValue(getVElement().getDomainModelReference(), getViewModelContext().getDomainModel());
212:                 final EStructuralFeature structuralFeature = (EStructuralFeature) observableValue.getValueType();
213:                 final EObject eObject = (EObject) ((IObserving) observableValue).getObserved();
214:                 observableValue.dispose();
215:
216:                 final int numColumns = 1 + getNumButtons();
217:
218:                 final Composite composite = new Composite(parent, SWT.NONE);
219:                 composite.setBackground(parent.getBackground());
220:                 GridLayoutFactory.fillDefaults().numColumns(numColumns).spacing(0, 0).equalWidth(false).applyTo(composite);
221:                 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.BEGINNING).applyTo(composite);
222:
223:                 mainComposite = new Composite(composite, SWT.NONE);
224:                 mainComposite.setBackground(parent.getBackground());
225:                 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).applyTo(mainComposite);
226:
227:                 stackLayout = new StackLayout();
228:                 mainComposite.setLayout(stackLayout);
229:
230:                 unsetLabel = new Label(mainComposite, SWT.CENTER);
231:                 unsetLabel.setText(getLocalizedString(MessageKeys.LinkControl_NotSet));
232:
233:                 unsetLabel.setBackground(mainComposite.getBackground());
234:                 unsetLabel.setForeground(composite.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
235:                 unsetLabel.setAlignment(SWT.CENTER);
236:
237:                 linkComposite = new Composite(mainComposite, SWT.NONE);
238:                 GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).applyTo(linkComposite);
239:                 linkComposite.setBackground(mainComposite.getBackground());
240:
241:                 createHyperlink();
242:                 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).applyTo(linkComposite);
243:
244:                 if (eObject.eIsSet(structuralFeature)) {
245:                         stackLayout.topControl = linkComposite;
246:                 } else {
247:                         stackLayout.topControl = unsetLabel;
248:                 }
249:                 createButtons(composite);
250:                 return composite;
251:         }
252:
253:         /**
254:          * Called by {@link #createSWTControl(Composite)} in order to create the buttons.
255:          *
256:          * @param parent the parent composite
257:          */
258:         protected void createButtons(Composite parent) {
259:                 String elementDisplayName = null;
260:                 try {
261:                         elementDisplayName = (String) emfFormsLabelProvider
262:                                 .getDisplayName(getVElement().getDomainModelReference(), getViewModelContext().getDomainModel())
263:                                 .getValue();
264:                 } catch (final NoLabelFoundException ex) {
265:                         getReportService().report(new AbstractReport(ex));
266:                 }
267:
268:                 VTReferenceStyleProperty referenceStyle = RendererUtil.getStyleProperty(
269:                         getVTViewTemplateProvider(), getVElement(), getViewModelContext(), VTReferenceStyleProperty.class);
270:                 if (referenceStyle == null) {
271:                         referenceStyle = getDefaultReferenceStyle();
272:                 }
273:
274:                 EReference eReference = null;
275:                 try {
276:                         eReference = (EReference) getModelValue().getValueType();
277:                 } catch (final DatabindingFailedException ex) {
278:                         getReportService().report(new AbstractReport(ex));
279:                 }
280:
281:                 if (eReference != null) {
282:                         if (eReference.isContainment()) {
283:                                 // Only allow to link existing elements in a containment reference if it was allowed in a reference
284:                                 // style property.
285:                                 if (referenceStyle.isShowLinkButtonForContainmentReferences()) {
286:                                         createAddReferenceButton(parent, elementDisplayName);
287:                                 }
288:                                 createNewReferenceButton(parent, elementDisplayName);
289:                         } else {
290:                                 createAddReferenceButton(parent, elementDisplayName);
291:                                 // Only allow to create new elements in a cross reference if it was allowed in a reference style
292:                                 // property.
293:                                 if (referenceStyle.isShowCreateAndLinkButtonForCrossReferences()) {
294:                                         createNewReferenceButton(parent, elementDisplayName);
295:                                 }
296:                         }
297:                 }
298:                 createDeleteReferenceButton(parent, elementDisplayName);
299:         }
300:
301:         /**
302:          * Creates and returns a default version of a {@link VTReferenceStyleProperty}.
303:          *
304:          * @return The default {@link VTReferenceStyleProperty}
305:          */
306:         protected VTReferenceStyleProperty getDefaultReferenceStyle() {
307:                 return VTReferenceFactory.eINSTANCE.createReferenceStyleProperty();
308:         }
309:
310:         /**
311:          * Called by {@link #createButtons(Composite)} to create the add existing reference button.
312:          *
313:          * @param parent the parent composite
314:          * @param elementDisplayName the display name of the reference
315:          */
316:         protected void createAddReferenceButton(Composite parent, String elementDisplayName) {
317:                 addReferenceBtn = new Button(parent, SWT.PUSH);
318:                 GridDataFactory.fillDefaults().grab(false, false).align(SWT.CENTER, SWT.CENTER).applyTo(addReferenceBtn);
319:                 addReferenceBtn.setImage(getAddReferenceButtonImage());
320:                 addReferenceBtn.setToolTipText(getLocalizedString(MessageKeys.LinkControl_AddReference) + elementDisplayName);
321:                 addReferenceBtn.addSelectionListener(new SelectionAdapter() {
322:                         @SuppressWarnings("unused")
323:                         private static final long serialVersionUID = 1L;
324:
325:                         @Override
326:                         public void widgetSelected(SelectionEvent e) {
327:                                 try {
328:                                         final EObject eObject = (EObject) ((IObserving) getModelValue()).getObserved();
329:                                         final EReference eReference = (EReference) getModelValue().getValueType();
330:                                         getReferenceService().addExistingModelElements(eObject, eReference);
331:                                 } catch (final DatabindingFailedException ex) {
332:                                         getReportService().report(new DatabindingFailedReport(ex));
333:                                 }
334:                         }
335:                 });
336:         }
337:
338:         /**
339:          * Returns the add reference image for button.
340:          *
341:          * @return the add reference image for button
342:          */
343:         protected Image getAddReferenceButtonImage() {
344:                 return getImage(getIconBundle(), "icons/reference.png"); //$NON-NLS-1$
345:         }
346:
347:         /**
348:          * Called by {@link #createButtons(Composite)} to create the create new reference button.
349:          *
350:          * @param parent the parent composite
351:          * @param elementDisplayName the display name of the reference
352:          */
353:         protected void createNewReferenceButton(Composite parent, String elementDisplayName) {
354:                 newReferenceBtn = new Button(parent, SWT.PUSH);
355:                 GridDataFactory.fillDefaults().grab(false, false).align(SWT.CENTER, SWT.CENTER).applyTo(newReferenceBtn);
356:                 newReferenceBtn.setImage(getNewReferenceButtonImage());
357:                 newReferenceBtn
358:                         .setToolTipText(getLocalizedString(MessageKeys.LinkControl_NewReference) + elementDisplayName);
359:                 newReferenceBtn.addSelectionListener(new SelectionAdapter() {
360:                         @SuppressWarnings("unused")
361:                         private static final long serialVersionUID = 1L;
362:
363:                         @Override
364:                         public void widgetSelected(SelectionEvent e) {
365:                                 try {
366:                                         final EObject eObject = (EObject) ((IObserving) getModelValue()).getObserved();
367:                                         final EReference eReference = (EReference) getModelValue().getValueType();
368:                                         getReferenceService().addNewModelElements(eObject, eReference, openNewReferenceInContext());
369:                                 } catch (final DatabindingFailedException ex) {
370:                                         getReportService().report(new DatabindingFailedReport(ex));
371:                                 }
372:                         }
373:                 });
374:         }
375:
376:         /**
377:          * Returns the new reference image for button.
378:          *
379:          * @return the new reference image for button
380:          */
381:         protected Image getNewReferenceButtonImage() {
382:                 return getImage(getIconBundle(), "icons/set_reference.png"); // //$NON-NLS-1$
383:         }
384:
385:         /**
386:          * Whether a new reference should be opened in a new context. True to open in new context, false otherwise.
387:          *
388:          * @return true to open in new context, false otherwise
389:          */
390:         protected boolean openNewReferenceInContext() {
391:                 return true;
392:         }
393:
394:         /**
395:          * Called by {@link #createButtons(Composite)} to create the delete reference button.
396:          *
397:          * @param parent the parent composite
398:          * @param elementDisplayName the display name of the reference
399:          */
400:         protected void createDeleteReferenceButton(Composite parent, String elementDisplayName) {
401:                 deleteReferenceButton = new Button(parent, SWT.PUSH);
402:                 GridDataFactory.fillDefaults().grab(false, false).align(SWT.CENTER, SWT.CENTER).applyTo(deleteReferenceButton);
403:                 deleteReferenceButton.setImage(getDeleteReferenceButtonImage());
404:                 deleteReferenceButton.setToolTipText(getLocalizedString(MessageKeys.LinkControl_DeleteReference));
405:                 deleteReferenceButton.addSelectionListener(new DeleteSelectionAdapter());
406:         }
407:
408:         /**
409:          * Returns the image for delete reference button.
410:          *
411:          * @return the image for delete reference button
412:          */
413:         protected Image getDeleteReferenceButtonImage() {
414:                 return getImage(getIconBundle(), "icons/unset_reference.png");//$NON-NLS-1$
415:         }
416:
417:         /**
418:          * Returns an image to be displayed given the bundle and path in the bundle where icon file can be found.
419:          * <p>
420:          * The image found is not meant to be disposed by user.
421:          * </p>
422:          *
423:          * @param bundle the bundle where the image file is located
424:          * @param iconPath the path of the icon file in the bundle
425:          * @return the image to be displayed.
426:          */
427:         protected Image getImage(Bundle bundle, String iconPath) {
428:                 return imageRegistryService != null ? imageRegistryService.getImage(bundle, iconPath) : null;
429:         }
430:
431:         /**
432:          * Returns the bundle where the icon file is located.
433:          *
434:          * @return the bundle where the icon file is located
435:          */
436:         protected Bundle getIconBundle() {
437:                 return FrameworkUtil.getBundle(LinkControlSWTRenderer.class);
438:         }
439:
440:         /**
441:          * Returns the link text to be used for the given linked {@code value}.
442:          *
443:          * @param value the value
444:          * @return The link text.
445:          * @throws DatabindingFailedException
446:          * @throws NoLabelFoundException
447:          */
448:         protected String getText(Object value) {
449:                 final String linkName = adapterFactoryItemDelegator.getText(value);
450:                 return linkName == null ? "" : linkName; //$NON-NLS-1$
451:         }
452:
453:         /**
454:          * Returns the image to be used for the given linked {@code value}.
455:          *
456:          * @param value the object for which the image is retrieved
457:          * @return the image
458:          */
459:         protected Image getImage(Object value) {
460:                 if (value == null) {
461:                         return null;
462:                 }
463:                 final Object imageDescription = adapterFactoryItemDelegator.getImage(value);
464:                 if (imageDescription == null) {
465:                         return null;
466:                 }
467:                 final Image image = org.eclipse.emf.ecp.edit.internal.swt.SWTImageHelper.getImage(imageDescription);
468:                 return image;
469:         }
470:
471:         private void createHyperlink() throws DatabindingFailedException {
472:                 imageHyperlink = new Label(linkComposite, SWT.NONE);
473:                 imageHyperlink.setBackground(linkComposite.getBackground());
474:
475:                 hyperlink = new Link(linkComposite, SWT.NONE);
476:                 hyperlink.setData(CUSTOM_VARIANT, "org_eclipse_emf_ecp_control_reference"); //$NON-NLS-1$
477:                 hyperlink.setBackground(linkComposite.getBackground());
478:                 hyperlink.addSelectionListener(new SelectionAdapter() {
479:                         @SuppressWarnings("unused")
480:                         private static final long serialVersionUID = 1L;
481:
482:                         @Override
483:                         public void widgetDefaultSelected(SelectionEvent e) {
484:                                 super.widgetDefaultSelected(e);
485:                                 widgetSelected(e);
486:                         }
487:
488:                         @Override
489:                         public void widgetSelected(SelectionEvent e) {
490:                                 super.widgetSelected(e);
491:                                 try {
492:                                         linkClicked((EObject) getModelValue().getValue());
493:                                 } catch (final DatabindingFailedException ex) {
494:                                         getReportService().report(new DatabindingFailedReport(ex));
495:                                 }
496:                         }
497:
498:                 });
499:                 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.BEGINNING).applyTo(hyperlink);
500:         }
501:
502:         /**
503:          * This code is called whenever the link of the link widget is clicked. You can overwrite this to change the
504:          * behavior.
505:          *
506:          * @param value the EObject that is linked
507:          */
508:         protected void linkClicked(EObject value) {
509:                 final ReferenceService referenceService = getReferenceService();
510:                 referenceService.openInNewContext(value);
511:         }
512:
513:         /**
514:          * @return the {@link ReferenceService}
515:          */
516:         protected ReferenceService getReferenceService() {
517:                 if (referenceService == null) {
518:                         referenceService = getViewModelContext().getService(ReferenceService.class);
519:                 }
520:                 return referenceService;
521:         }
522:
523:         private String getLocalizedString(String key) {
524:                 return localizationService.getString(LinkControlSWTRenderer.class, key);
525:         }
526:
527:         /**
528:          * @return number of buttons added by the link control.
529:          */
530:         protected int getNumButtons() {
531:                 return 3;
532:         }
533:
534:         @Override
535:         protected String getUnsetText() {
536:                 return getLocalizedString(MessageKeys.LinkControl_NoLinkSetClickToSetLink);
537:         }
538:
539:         @Override
540:         protected void postInit() {
541:                 super.postInit();
542:                 composedAdapterFactory = new ComposedAdapterFactory(new AdapterFactory[] {
543:                         new CustomReflectiveItemProviderAdapterFactory(),
544:                         new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE) });
545:                 adapterFactoryItemDelegator = new AdapterFactoryItemDelegator(composedAdapterFactory);
546:         }
547:
548:         @Override
549:         protected void dispose() {
550:                 if (modelElementChangeListener != null) {
551:                         modelElementChangeListener.remove();
552:                 }
553:                 if (composedAdapterFactory != null) {
554:                         composedAdapterFactory.dispose();
555:                 }
556:                 super.dispose();
557:         }
558:
559:         private void updateChangeListener(EObject value) {
560:                 if (modelElementChangeListener != null) {
561:                         if (modelElementChangeListener.getTarget().equals(value)) {
562:                                 return;
563:                         }
564:                         modelElementChangeListener.remove();
565:                         modelElementChangeListener = null;
566:                 }
567:                 if (value == null) {
568:                         if (stackLayout.topControl != unsetLabel) {
569:                                 stackLayout.topControl = unsetLabel;
570:                                 mainComposite.layout();
571:                         }
572:
573:                 } else {
574:                         if (stackLayout.topControl != linkComposite) {
575:                                 stackLayout.topControl = linkComposite;
576:                                 mainComposite.layout();
577:                                 // At least on Windows, the hyperlink size needs to be recalculated asynchronously after its value has
578:                                 // updated. Otherwise, the hyperlink has a size of 0 when the control is initially rendered without a
579:                                 // value.
580:                                 Display.getDefault().asyncExec(() -> linkComposite.layout());
581:                         }
582:
583:                         modelElementChangeListener = new ECPModelElementChangeListener(value) {
584:
585:                                 @Override
586:                                 public void onChange(Notification notification) {
587:                                         Display.getDefault().syncExec(new Runnable() {
588:
589:                                                 @Override
590:                                                 public void run() {
591:                                                         getDataBindingContext().updateTargets();
592:                                                         linkComposite.layout();
593:                                                 }
594:                                         });
595:                                 }
596:                         };
597:                 }
598:         }
599:
600:         @Override
601:         public void scrollToReveal() {
602:                 if (canReveal(addReferenceBtn) && addReferenceBtn.isEnabled()) {
603:                         scrollToReveal(addReferenceBtn);
604:                 } else if (canReveal(newReferenceBtn) && newReferenceBtn.isEnabled()) {
605:                         scrollToReveal(newReferenceBtn);
606:                 } else {
607:                         super.scrollToReveal();
608:                 }
609:         }
610:
611:         @Override
612:         protected void applyReadOnly() {
613:                 super.applyReadOnly();
614:                 updateButtonVisibility();
615:                 if (isRenderingFinished()) {
616:                         mainComposite.getParent().layout();
617:                 }
618:         }
619:
620:         /**
621:          * Updates the visibility of 'add reference', 'new reference', and 'delete reference' buttons according to the bound
622:          * input.
623:          */
624:         protected void updateButtonVisibility() {
625:                 final boolean isVisible = !getVElement().isEffectivelyReadonly();
626:
627:                 // Check for null because not all buttons might have been created
628:                 if (addReferenceBtn != null) {
629:                         addReferenceBtn.setVisible(isVisible);
630:                         GridData.class.cast(addReferenceBtn.getLayoutData()).exclude = !isVisible;
631:                 }
632:                 if (newReferenceBtn != null) {
633:                         newReferenceBtn.setVisible(isVisible);
634:                         GridData.class.cast(newReferenceBtn.getLayoutData()).exclude = !isVisible;
635:                 }
636:                 if (deleteReferenceButton != null) {
637:                         deleteReferenceButton.setVisible(isVisible);
638:                         GridData.class.cast(deleteReferenceButton.getLayoutData()).exclude = !isVisible;
639:                 }
640:         }
641:
642:         /** Selection listener for the delete reference button. */
643:         class DeleteSelectionAdapter extends SelectionAdapter {
644:                 @SuppressWarnings("unused")
645:                 private static final long serialVersionUID = 1L;
646:
647:                 @Override
648:                 public void widgetSelected(SelectionEvent e) {
649:                         try {
650:                                 final EReference reference = (EReference) getModelValue().getValueType();
651:                                 final EObject object = getViewModelContext().getDomainModel();
652:                                 if (reference.isContainment()) {
653:                                         if (askConfirmation(object)) {
654:                                                 delete(object, reference);
655:                                         }
656:                                 } else {
657:                                         delete(object, reference);
658:                                 }
659:                         } catch (final DatabindingFailedException ex) {
660:                                 getReportService().report(new DatabindingFailedReport(ex));
661:                         }
662:                 }
663:
664:                 private void delete(EObject eObject, EReference reference) {
665:                         final EditingDomain editingDomain = getEditingDomain(eObject);
666:                         final Command removeCommand = SetCommand.create(editingDomain, eObject,
667:                                 reference, null);
668:                         if (removeCommand.canExecute()) {
669:                                 editingDomain.getCommandStack().execute(removeCommand);
670:                         }
671:                 }
672:
673:                 private boolean askConfirmation(EObject eObject) {
674:                         final String modelElementName = getText(eObject);
675:                         final String question = getLocalizedString(MessageKeys.LinkControl_DeleteModelQuestion)
676:                                 + modelElementName
677:                                 + getLocalizedString(MessageKeys.LinkControl_QuestionMark);
678:                         final MessageDialog dialog = new MessageDialog(
679:                                 null,
680:                                 getLocalizedString(MessageKeys.LinkControl_DeleteReferenceConfirmation),
681:                                 null,
682:                                 question,
683:                                 MessageDialog.QUESTION,
684:                                 new String[] {
685:                                         getLocalizedString(MessageKeys.LinkControl_DeleteReferenceYes),
686:                                         getLocalizedString(MessageKeys.LinkControl_DeleteReferenceNo) },
687:                                 0);
688:
689:                         boolean confirm = false;
690:                         if (dialog.open() == Window.OK) {
691:                                 confirm = true;
692:                         }
693:                         return confirm;
694:                 }
695:         }
696: }