Skip to content

Package: MultiAttributeSWTRenderer$ECPListEditingSupport$ColumnViewerEditorActivationListenerHelper

MultiAttributeSWTRenderer$ECPListEditingSupport$ColumnViewerEditorActivationListenerHelper

nameinstructionbranchcomplexitylinemethod
MultiAttributeSWTRenderer.ECPListEditingSupport.ColumnViewerEditorActivationListenerHelper(MultiAttributeSWTRenderer.ECPListEditingSupport)
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%
afterEditorActivated(ColumnViewerEditorActivationEvent)
M: 0 C: 1
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
afterEditorDeactivated(ColumnViewerEditorDeactivationEvent)
M: 7 C: 23
77%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 1 C: 6
86%
M: 0 C: 1
100%
beforeEditorActivated(ColumnViewerEditorActivationEvent)
M: 1 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
beforeEditorDeactivated(ColumnViewerEditorDeactivationEvent)
M: 0 C: 1
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: * David Soto Setzke - initial API and implementation
13: * Johannes Faltermeier - initial API and implementation
14: * Christian W. Damus - bug 543348
15: ******************************************************************************/
16: package org.eclipse.emfforms.spi.view.control.multiattribute;
17:
18: import java.lang.reflect.InvocationTargetException;
19:
20: import javax.inject.Inject;
21:
22: import org.eclipse.core.databinding.Binding;
23: import org.eclipse.core.databinding.observable.IObserving;
24: import org.eclipse.core.databinding.observable.list.IObservableList;
25: import org.eclipse.core.databinding.observable.value.IObservableValue;
26: import org.eclipse.emf.common.notify.AdapterFactory;
27: import org.eclipse.emf.databinding.EMFDataBindingContext;
28: import org.eclipse.emf.ecore.EAttribute;
29: import org.eclipse.emf.ecore.EClass;
30: import org.eclipse.emf.ecore.EObject;
31: import org.eclipse.emf.ecore.InternalEObject;
32: import org.eclipse.emf.ecore.impl.DynamicEObjectImpl;
33: import org.eclipse.emf.ecore.util.EcoreUtil;
34: import org.eclipse.emf.ecp.edit.spi.swt.table.ECPCellEditor;
35: import org.eclipse.emf.ecp.view.model.common.edit.provider.CustomReflectiveItemProviderAdapterFactory;
36: import org.eclipse.emf.ecp.view.model.common.util.RendererUtil;
37: import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
38: import org.eclipse.emf.ecp.view.spi.core.swt.AbstractControlSWTRenderer;
39: import org.eclipse.emf.ecp.view.spi.model.VControl;
40: import org.eclipse.emf.ecp.view.spi.model.VDomainModelReference;
41: import org.eclipse.emf.ecp.view.spi.provider.ECPTooltipModifierHelper;
42: import org.eclipse.emf.ecp.view.spi.renderer.NoPropertyDescriptorFoundExeption;
43: import org.eclipse.emf.ecp.view.spi.renderer.NoRendererFoundException;
44: import org.eclipse.emf.ecp.view.spi.swt.reporting.RenderingFailedReport;
45: import org.eclipse.emf.ecp.view.spi.util.swt.ImageRegistryService;
46: import org.eclipse.emf.ecp.view.template.model.VTViewTemplateProvider;
47: import org.eclipse.emf.ecp.view.template.style.tableStyleProperty.model.RenderMode;
48: import org.eclipse.emf.ecp.view.template.style.tableStyleProperty.model.VTTableStyleProperty;
49: import org.eclipse.emf.ecp.view.template.style.tableStyleProperty.model.VTTableStylePropertyFactory;
50: import org.eclipse.emf.edit.command.AddCommand;
51: import org.eclipse.emf.edit.command.MoveCommand;
52: import org.eclipse.emf.edit.command.RemoveCommand;
53: import org.eclipse.emf.edit.domain.EditingDomain;
54: import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
55: import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
56: import org.eclipse.emfforms.internal.view.control.multiattribute.Messages;
57: import org.eclipse.emfforms.internal.view.control.multiattribute.celleditor.CellEditorFactory;
58: import org.eclipse.emfforms.spi.common.report.AbstractReport;
59: import org.eclipse.emfforms.spi.common.report.ReportService;
60: import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedException;
61: import org.eclipse.emfforms.spi.core.services.databinding.EMFFormsDatabinding;
62: import org.eclipse.emfforms.spi.core.services.label.EMFFormsLabelProvider;
63: import org.eclipse.emfforms.spi.core.services.label.NoLabelFoundException;
64: import org.eclipse.emfforms.spi.swt.core.SWTDataElementIdHelper;
65: import org.eclipse.emfforms.spi.swt.core.layout.GridDescriptionFactory;
66: import org.eclipse.emfforms.spi.swt.core.layout.SWTGridCell;
67: import org.eclipse.emfforms.spi.swt.core.layout.SWTGridDescription;
68: import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
69: import org.eclipse.jface.layout.GridDataFactory;
70: import org.eclipse.jface.layout.GridLayoutFactory;
71: import org.eclipse.jface.layout.TableColumnLayout;
72: import org.eclipse.jface.viewers.CellEditor;
73: import org.eclipse.jface.viewers.ColumnViewer;
74: import org.eclipse.jface.viewers.ColumnViewerEditor;
75: import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
76: import org.eclipse.jface.viewers.ColumnViewerEditorActivationListener;
77: import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
78: import org.eclipse.jface.viewers.ColumnViewerEditorDeactivationEvent;
79: import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
80: import org.eclipse.jface.viewers.ColumnWeightData;
81: import org.eclipse.jface.viewers.EditingSupport;
82: import org.eclipse.jface.viewers.ISelectionChangedListener;
83: import org.eclipse.jface.viewers.IStructuredSelection;
84: import org.eclipse.jface.viewers.SelectionChangedEvent;
85: import org.eclipse.jface.viewers.TableViewer;
86: import org.eclipse.jface.viewers.TableViewerColumn;
87: import org.eclipse.jface.viewers.TableViewerEditor;
88: import org.eclipse.jface.viewers.TableViewerRow;
89: import org.eclipse.jface.viewers.ViewerCell;
90: import org.eclipse.swt.SWT;
91: import org.eclipse.swt.events.SelectionAdapter;
92: import org.eclipse.swt.events.SelectionEvent;
93: import org.eclipse.swt.graphics.Image;
94: import org.eclipse.swt.layout.GridLayout;
95: import org.eclipse.swt.widgets.Button;
96: import org.eclipse.swt.widgets.Composite;
97: import org.eclipse.swt.widgets.Control;
98: import org.eclipse.swt.widgets.Display;
99: import org.eclipse.swt.widgets.Label;
100: import org.eclipse.swt.widgets.Table;
101: import org.eclipse.swt.widgets.TableItem;
102: import org.osgi.framework.FrameworkUtil;
103:
104: /**
105: * Renderer for MultiReferenceControl.
106: *
107: * @author David Soto Setzke
108: * @author Johannes Faltermeier
109: *
110: */
111: public class MultiAttributeSWTRenderer extends AbstractControlSWTRenderer<VControl> {
112:
113:         private static final String ICON_ADD = "icons/add.png"; //$NON-NLS-1$
114:         private static final String ICON_DELETE = "icons/delete.png"; //$NON-NLS-1$
115:         private static final String ICONS_ARROW_DOWN_PNG = "icons/arrow_down.png";//$NON-NLS-1$
116:         private static final String ICONS_ARROW_UP_PNG = "icons/arrow_up.png";//$NON-NLS-1$
117:
118:         private final ImageRegistryService imageRegistryService;
119:
120:         private AdapterFactoryLabelProvider labelProvider;
121:         private ComposedAdapterFactory composedAdapterFactory;
122:
123:         private Composite mainComposite;
124:         private TableViewer tableViewer;
125:         private Button removeButton;
126:         private Button addButton;
127:
128:         private final EMFDataBindingContext viewModelDBC;
129:         private Label validationIcon;
130:         private AddButtonSelectionAdapter addButtonSelectionAdapter;
131:         private RemoveButtonSelectionAdapter removeButtonSelectionAdapter;
132:         private UpButtonSelectionAdapter upButtonSelectionAdapter;
133:         private DownButtonSelectionAdapter downButtonSelectionAdapter;
134:         private ECPListEditingSupport observableSupport;
135:         private SWTGridDescription rendererGridDescription;
136:         private Button upButton;
137:         private Button downButton;
138:
139:         /**
140:          * Default constructor.
141:          *
142:          * @param vElement
143:          * the view model element to be rendered
144:          * @param viewContext
145:          * the view context
146:          * @param emfFormsDatabinding
147:          * The {@link EMFFormsDatabinding}
148:          * @param emfFormsLabelProvider
149:          * The {@link EMFFormsLabelProvider}
150:          * @param reportService
151:          * The {@link ReportService}
152:          * @param vtViewTemplateProvider
153:          * The {@link VTViewTemplateProvider}
154:          * @param imageRegistryService
155:          * The {@link ImageRegistryService}
156:          */
157:         @Inject
158:         public MultiAttributeSWTRenderer(VControl vElement, ViewModelContext viewContext, ReportService reportService,
159:                 EMFFormsDatabinding emfFormsDatabinding, EMFFormsLabelProvider emfFormsLabelProvider,
160:                 VTViewTemplateProvider vtViewTemplateProvider, ImageRegistryService imageRegistryService) {
161:                 super(vElement, viewContext, reportService, emfFormsDatabinding, emfFormsLabelProvider, vtViewTemplateProvider);
162:                 this.imageRegistryService = imageRegistryService;
163:                 viewModelDBC = new EMFDataBindingContext();
164:         }
165:
166:         /**
167:          * Creates the default {@link VTTableStyleProperty}.
168:          *
169:          * @return the default {@link VTTableStyleProperty}
170:          * @since 1.14
171:          */
172:         protected VTTableStyleProperty createDefaultTableStyleProperty() {
173:                 return VTTableStylePropertyFactory.eINSTANCE.createTableStyleProperty();
174:         }
175:
176:         /**
177:          * Returns the {@link VTTableStyleProperty}.
178:          *
179:          * @return the {@link VTTableStyleProperty}
180:          * @since 1.14
181:          */
182:         protected VTTableStyleProperty getTableStyleProperty() {
183:                 VTTableStyleProperty styleProperty = RendererUtil.getStyleProperty(getVTViewTemplateProvider(), getVElement(),
184:                         getViewModelContext(), VTTableStyleProperty.class);
185:                 if (styleProperty == null) {
186:                         styleProperty = createDefaultTableStyleProperty();
187:                 }
188:                 return styleProperty;
189:         }
190:
191:         @Override
192:         public SWTGridDescription getGridDescription(SWTGridDescription gridDescription) {
193:                 if (rendererGridDescription == null) {
194:                         // create special grid for compact mode
195:                         if (getTableStyleProperty().getRenderMode() == RenderMode.COMPACT_VERTICALLY) {
196:                                 rendererGridDescription = GridDescriptionFactory.INSTANCE.createCompactGrid(false, true, this);
197:                         } else {
198:                                 rendererGridDescription = GridDescriptionFactory.INSTANCE.createSimpleGrid(1, 1, this);
199:                         }
200:
201:                 }
202:                 return rendererGridDescription;
203:         }
204:
205:         /**
206:          * Returns the height for the table that will be created.
207:          *
208:          * @return the height hint
209:          */
210:         protected int getTableHeightHint() {
211:                 return 200;
212:         }
213:
214:         /**
215:          * Gives access to the tableViewer used to display the attributes.
216:          *
217:          * @return the viewer
218:          */
219:         protected TableViewer getTableViewer() {
220:                 return tableViewer;
221:         }
222:
223:         /**
224:          * Creates the composite which will be the parent for the table.
225:          *
226:          * @param composite
227:          * the parent composite
228:          * @return the table composite
229:          */
230:         protected Composite createControlComposite(Composite composite) {
231:                 final Composite controlComposite = new Composite(composite, SWT.NONE);
232:                 GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).hint(1, getTableHeightHint())
233:                         .applyTo(controlComposite);
234:                 GridLayoutFactory.fillDefaults().numColumns(1).applyTo(controlComposite);
235:                 return controlComposite;
236:         }
237:
238:         /**
239:          * Returns an {@link Image} from the image registry.
240:          *
241:          * @param path
242:          * the path to the image
243:          * @return the image
244:          */
245:         protected Image getImage(String path) {
246:                 return imageRegistryService.getImage(FrameworkUtil.getBundle(MultiAttributeSWTRenderer.class), path);
247:         }
248:
249:         private Button createRemoveRowButton(final Composite buttonComposite, IObservableList list) {
250:                 final EAttribute attribute = EAttribute.class.cast(list.getElementType());
251:                 final Button removeButton = new Button(buttonComposite, SWT.None);
252:                 SWTDataElementIdHelper.setElementIdDataWithSubId(removeButton, getVElement(), "remove", getViewModelContext()); //$NON-NLS-1$
253:                 final Image image = getImage(ICON_DELETE);
254:                 removeButton.setImage(image);
255:                 removeButton.setEnabled(!getVElement().isEffectivelyReadonly());
256:                 if (list.size() <= attribute.getLowerBound()) {
257:                         removeButton.setEnabled(false);
258:                 }
259:                 return removeButton;
260:         }
261:
262:         private Button createAddRowButton(final Composite buttonComposite, IObservableList list) {
263:                 final EAttribute attribute = EAttribute.class.cast(list.getElementType());
264:                 final Button addButton = new Button(buttonComposite, SWT.None);
265:                 SWTDataElementIdHelper.setElementIdDataWithSubId(addButton, getVElement(), "add", getViewModelContext()); //$NON-NLS-1$
266:                 final Image image = getImage(ICON_ADD);
267:                 addButton.setImage(image);
268:                 if (attribute.getUpperBound() != -1 && list.size() >= attribute.getUpperBound()) {
269:                         addButton.setEnabled(false);
270:                 }
271:                 addButton.setToolTipText(Messages.MultiAttributeSWTRenderer_AddButtonTooltip);
272:                 return addButton;
273:         }
274:
275:         @Override
276:         protected void applyReadOnly() {
277:                 // do not let the super method disable the control, so the table is still enabled for sorting for example
278:                 // when applying read only, all buttons shall be hidden
279:                 updateButtonVisibility();
280:         }
281:
282:         @Override
283:         protected boolean ignoreEnableOnReadOnly() {
284:                 // always take the enable state into account (read only but enable let the user sort the table content for
285:                 // example)
286:                 return false;
287:         }
288:
289:         /**
290:          * Updates button visibility and enablement.
291:          */
292:         protected void updateButtons() {
293:                 updateButtonVisibility();
294:                 updateButtonEnabling();
295:         }
296:
297:         /**
298:          * Updates the visibility of 'Add', 'Remove', 'Up', 'Down' buttons according to the bound input.
299:          */
300:         protected void updateButtonVisibility() {
301:                 final boolean isVisible = !getVElement().isEffectivelyReadonly();
302:
303:                 if (addButton != null) {
304:                         addButton.setVisible(isVisible);
305:                 }
306:                 if (removeButton != null) {
307:                         removeButton.setVisible(isVisible);
308:                 }
309:                 if (upButton != null) {
310:                         upButton.setVisible(isVisible);
311:                 }
312:                 if (downButton != null) {
313:                         downButton.setVisible(isVisible);
314:                 }
315:         }
316:
317:         /**
318:          * Updates the enablement of 'addExisting', 'addNew', 'delete', 'moveUp' and 'moveDown' buttons according to the
319:          * bound input.
320:          */
321:         protected void updateButtonEnabling() {
322:                 final boolean isEnable = getVElement().isEffectivelyEnabled();
323:                 final int listSize = tableViewer != null ? tableViewer.getTable().getItemCount() : 0;
324:                 final int selectionIndex = tableViewer != null ? tableViewer.getTable().getSelectionIndex() : -1;
325:
326:                 enableUpButton(isEnable, listSize, selectionIndex);
327:                 enableDownButton(isEnable, listSize, selectionIndex);
328:                 enableAddButton(isEnable, listSize, selectionIndex);
329:                 enableDeleteButton(isEnable, listSize, selectionIndex);
330:         }
331:
332:         private void enableUpButton(boolean baseEnable, int listSize, int selectionIndex) {
333:                 if (upButton != null) {
334:                         final boolean enabled = baseEnable && listSize > 1 && selectionIndex > 0;
335:                         upButton.setEnabled(enabled);
336:                 }
337:         }
338:
339:         private void enableDownButton(boolean baseEnable, int listSize, int selectionIndex) {
340:                 if (downButton != null) {
341:                         final boolean enabled = baseEnable && listSize > 1 && selectionIndex != -1 && selectionIndex < listSize - 1;
342:                         downButton.setEnabled(enabled);
343:                 }
344:         }
345:
346:         private void enableAddButton(boolean baseEnable, int listSize, int selectionIndex) {
347:                 if (addButton != null) {
348:                         addButton.setEnabled(baseEnable);
349:                 }
350:         }
351:
352:         private void enableDeleteButton(boolean baseEnable, int listSize, int selectionIndex) {
353:                 if (removeButton != null) {
354:                         removeButton.setEnabled(baseEnable && listSize > 0 && selectionIndex != -1);
355:                 }
356:         }
357:
358:         @Override
359:         protected Control renderControl(SWTGridCell cell, Composite parent)
360:                 throws NoPropertyDescriptorFoundExeption, NoRendererFoundException {
361:                 if (rendererGridDescription.getColumns() == 1) {
362:                         // Default
363:                         return renderMultiAttributeControl(cell, parent);
364:                 }
365:                 // Compact: render validation icon
366:                 if (cell.getColumn() == 0 && rendererGridDescription.getColumns() > 1) {
367:                         validationIcon = createValidationIcon(parent);
368:                         GridDataFactory.fillDefaults().hint(16, 17).grab(false, false).applyTo(validationIcon);
369:                         return validationIcon;
370:                 }
371:                 // Compact: render list and buttons next to each other
372:                 final Composite composite = new Composite(parent, SWT.NONE);
373:                 composite.setBackground(parent.getBackground());
374:
375:                 try {
376:                         final IObservableList list = getEMFFormsDatabinding().getObservableList(
377:                                 getVElement().getDomainModelReference(),
378:                                 getViewModelContext().getDomainModel());
379:
380:                         GridLayoutFactory.fillDefaults().numColumns(2).applyTo(composite);
381:                         final Control multiAttributeComposite = renderMultiAttributeControl(cell, composite);
382:                         GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(multiAttributeComposite);
383:                         final Composite buttonComposite = createButtonComposite(composite, list);
384:                         GridDataFactory.fillDefaults().align(SWT.END, SWT.BEGINNING).grab(false, false).applyTo(buttonComposite);
385:                         initButtons(list);
386:
387:                 } catch (final DatabindingFailedException ex) {
388:                         getReportService().report(new RenderingFailedReport(ex));
389:                         return createErrorLabel(composite, ex);
390:                 }
391:                 return composite;
392:         }
393:
394:         /**
395:          * Renders the MultiAttribute Control.
396:          *
397:          * Renders the MultiReference control including validation and buttons when {@link RenderMode} is set to
398:          * {@link RenderMode#DEFAULT}. Only renders the
399:          * MultiReferfence control without validation and buttons when renderMode is set to
400:          * {@link RenderMode#COMPACT_VERTICALLY}.
401:          *
402:          * @param cell the {@link SWTGridCell}.
403:          * @param parent the {@link Composite}.
404:          * @return the rendered {@link Control}
405:          * @throws NoRendererFoundException the {@link NoRendererFoundException}.
406:          * @throws NoPropertyDescriptorFoundExeption the {@link NoPropertyDescriptorFoundExeption}.
407:          * @since 1.14
408:          */
409:         protected Control renderMultiAttributeControl(SWTGridCell cell, Composite parent)
410:                 throws NoRendererFoundException, NoPropertyDescriptorFoundExeption {
411:
412:                 final Composite composite = new Composite(parent, SWT.NONE);
413:                 composite.setBackground(parent.getBackground());
414:
415:                 if (getTableStyleProperty().getRenderMode() == RenderMode.COMPACT_VERTICALLY) {
416:                         // Avoid the default margins of "new GridLayout()"
417:                         GridLayoutFactory.fillDefaults().applyTo(composite);
418:                 } else {
419:                         composite.setLayout(new GridLayout(1, false));
420:                 }
421:
422:                 createLabelProvider();
423:
424:                 IObservableList list;
425:                 try {
426:                         list = getEMFFormsDatabinding().getObservableList(getVElement().getDomainModelReference(),
427:                                 getViewModelContext().getDomainModel());
428:                 } catch (final DatabindingFailedException ex1) {
429:                         getReportService().report(new RenderingFailedReport(ex1));
430:                         return composite;
431:                 }
432:
433:                 if (getTableStyleProperty().getRenderMode() == RenderMode.DEFAULT) {
434:                         final Composite titleComposite = createTitleComposite(composite);
435:                         createButtonComposite(titleComposite, list);
436:                 }
437:
438:                 final Composite controlComposite = createControlComposite(composite);
439:                 createContent(controlComposite, list);
440:
441:                 SWTDataElementIdHelper.setElementIdDataForVControl(composite, getVElement(), getViewModelContext());
442:
443:                 if (getTableStyleProperty().getRenderMode() == RenderMode.DEFAULT) {
444:                         initButtons(list);
445:                 }
446:
447:                 return composite;
448:         }
449:
450:         /**
451:          * Creates the Title Composite containing validation and buttons. Buttons have to be initialized afterwards.
452:          *
453:          * @param parent the parent {@link Composite}.
454:          * @return the created {@link Composite}.
455:          * @since 1.14
456:          */
457:         protected Composite createTitleComposite(Composite parent) {
458:                 final Composite titleComposite = new Composite(parent, SWT.NONE);
459:                 titleComposite.setBackground(parent.getBackground());
460:                 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.BEGINNING).applyTo(titleComposite);
461:                 GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).applyTo(titleComposite);
462:
463:                 validationIcon = createValidationIcon(titleComposite);
464:                 GridDataFactory.fillDefaults().hint(16, 17).grab(false, false).applyTo(validationIcon);
465:                 return titleComposite;
466:         }
467:
468:         /**
469:          * Create the button composite. Buttons have to be initialized after the table is created.
470:          *
471:          * @param parent the {@link Composite} parent.
472:          * @param list the {@link IObservableList}.
473:          * @return the created {@link Composite}.
474:          * @since 1.14
475:          */
476:         protected Composite createButtonComposite(Composite parent, IObservableList list) {
477:                 final Composite buttonComposite = new Composite(parent, SWT.NONE);
478:
479:                 final EAttribute attribute = EAttribute.class.cast(list.getElementType());
480:
481:                 buttonComposite.setBackground(parent.getBackground());
482:                 GridDataFactory.fillDefaults().align(SWT.END, SWT.BEGINNING).grab(true, false).applyTo(buttonComposite);
483:                 int numButtons = 0;
484:                 if (attribute.isOrdered()) {
485:                         createUpDownButtons(buttonComposite, list);
486:                         numButtons += 2;
487:                 }
488:
489:                 addButton = createAddRowButton(buttonComposite, list);
490:                 removeButton = createRemoveRowButton(buttonComposite, list);
491:                 numButtons += 2;
492:
493:                 GridLayoutFactory.fillDefaults().numColumns(numButtons).equalWidth(false).applyTo(buttonComposite);
494:                 return buttonComposite;
495:         }
496:
497:         /**
498:          * Initializes the buttons. Call this after table is created.
499:          *
500:          * @param list the {@link IObservableList}.
501:          * @since 1.14
502:          */
503:         protected void initButtons(IObservableList list) {
504:                 initAddButton(addButton, list);
505:                 initRemoveButton(removeButton, list);
506:                 initUpButton(upButton, list);
507:                 initDownButton(downButton, list);
508:
509:                 getTableViewer().addSelectionChangedListener(new ISelectionChangedListener() {
510:                         @Override
511:                         public void selectionChanged(SelectionChangedEvent event) {
512:                                 updateButtonEnabling();
513:                         }
514:                 });
515:                 updateButtons();
516:         }
517:
518:         private void createLabelProvider() {
519:                 composedAdapterFactory = new ComposedAdapterFactory(
520:                         new AdapterFactory[] { new CustomReflectiveItemProviderAdapterFactory(),
521:                                 new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE) });
522:                 labelProvider = new AdapterFactoryLabelProvider(composedAdapterFactory);
523:                 labelProvider.setFireLabelUpdateNotifications(true);
524:         }
525:
526:         private void initAddButton(Button addButton, IObservableList list) {
527:                 if (addButton == null) {
528:                         return;
529:                 }
530:                 addButtonSelectionAdapter = new AddButtonSelectionAdapter(list);
531:                 addButton.addSelectionListener(addButtonSelectionAdapter);
532:         }
533:
534:         private void initRemoveButton(Button removeButton, IObservableList list) {
535:                 if (removeButton == null) {
536:                         return;
537:                 }
538:                 removeButtonSelectionAdapter = new RemoveButtonSelectionAdapter(list);
539:                 removeButton.addSelectionListener(removeButtonSelectionAdapter);
540:         }
541:
542:         private void initUpButton(Button upButton, IObservableList list) {
543:                 if (upButton == null) {
544:                         return;
545:                 }
546:                 upButtonSelectionAdapter = new UpButtonSelectionAdapter(list);
547:                 upButton.addSelectionListener(upButtonSelectionAdapter);
548:                 upButton.setEnabled(false);
549:         }
550:
551:         private void initDownButton(Button downButton, IObservableList list) {
552:                 if (downButton == null) {
553:                         return;
554:                 }
555:                 downButtonSelectionAdapter = new DownButtonSelectionAdapter(list);
556:                 downButton.addSelectionListener(downButtonSelectionAdapter);
557:                 // by default, button should not be enabled (selection is empty)
558:                 downButton.setEnabled(false);
559:         }
560:
561:         /**
562:          * Create the up and down buttons.
563:          *
564:          * @param composite The {@link Composite} to create the buttons on
565:          * @param list The {@link IObservableList} of the current {@link MultiAttributeSWTRenderer}
566:          * @since 1.17
567:          */
568:         protected void createUpDownButtons(Composite composite, IObservableList list) {
569:                 final Image up = getImage(ICONS_ARROW_UP_PNG);
570:                 final Image down = getImage(ICONS_ARROW_DOWN_PNG);
571:
572:                 upButton = new Button(composite, SWT.PUSH);
573:                 SWTDataElementIdHelper.setElementIdDataWithSubId(upButton, getVElement(), "up", getViewModelContext()); //$NON-NLS-1$
574:                 upButton.setImage(up);
575:                 upButton.setEnabled(!getVElement().isEffectivelyReadonly());
576:
577:                 downButton = new Button(composite, SWT.PUSH);
578:                 SWTDataElementIdHelper.setElementIdDataWithSubId(downButton, getVElement(), "down", getViewModelContext()); //$NON-NLS-1$
579:                 downButton.setImage(down);
580:                 downButton.setEnabled(!getVElement().isEffectivelyReadonly());
581:         }
582:
583:         private InternalEObject getInstanceOf(EClass clazz) {
584:                 EObject tempInstance;
585:                 if (clazz.isInterface() || clazz.isAbstract() || clazz.getInstanceClass() == null) {
586:                         tempInstance = new DynamicEObjectImpl(clazz);
587:                 } else {
588:                         tempInstance = EcoreUtil.create(clazz);
589:                 }
590:                 return InternalEObject.class.cast(tempInstance);
591:         }
592:
593:         private void createContent(Composite composite, IObservableList list) {
594:                 final EAttribute attribute = EAttribute.class.cast(list.getElementType());
595:                 tableViewer = new TableViewer(composite, SWT.MULTI | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
596:                 tableViewer.getTable().setData(CUSTOM_VARIANT, "org_eclipse_emf_ecp_control_multiattribute"); //$NON-NLS-1$
597:                 tableViewer.getTable().setHeaderVisible(true);
598:                 tableViewer.getTable().setLinesVisible(true);
599:
600:                 final ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(tableViewer) {
601:                         @Override
602:                         protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) {
603:                                 if (getVElement().isEffectivelyReadonly()) {
604:                                         return false;
605:                                 }
606:                                 return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL
607:                                         || event.eventType == ColumnViewerEditorActivationEvent.MOUSE_CLICK_SELECTION
608:                                         || event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.CR
609:                                         || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC;
610:                         }
611:                 };
612:
613:                 TableViewerEditor.create(tableViewer, null, actSupport,
614:                         ColumnViewerEditor.TABBING_HORIZONTAL | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR
615:                                 | ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION);
616:                 ColumnViewerToolTipSupport.enableFor(tableViewer);
617:
618:                 final ObservableListContentProvider cp = new ObservableListContentProvider();
619:
620:                 final EMFFormsLabelProvider labelService = getEMFFormsLabelProvider();
621:
622:                 final TableViewerColumn column = new TableViewerColumn(tableViewer, SWT.NONE);
623:                 column.getColumn().setResizable(false);
624:                 column.getColumn().setMoveable(false);
625:
626:                 final EClass clazz = attribute.getEContainingClass();
627:                 InternalEObject tempInstance = null;
628:                 if (!clazz.isAbstract() && !clazz.isInterface()) {
629:                         tempInstance = getInstanceOf(clazz);
630:                 }
631:
632:                 final CellEditor cellEditor = createCellEditor(tempInstance, attribute, tableViewer.getTable());
633:
634:                 final IObservableValue textObservableValue = org.eclipse.jface.databinding.swt.typed.WidgetProperties.text()
635:                         .observe(column.getColumn());
636:                 final IObservableValue tooltipObservableValue = org.eclipse.jface.databinding.swt.typed.WidgetProperties
637:                         .tooltipText()
638:                         .observe(column.getColumn());
639:                 try {
640:                         viewModelDBC.bindValue(textObservableValue, labelService
641:                                 .getDisplayName(getVElement().getDomainModelReference(), getViewModelContext().getDomainModel()));
642:
643:                         viewModelDBC.bindValue(tooltipObservableValue, labelService
644:                                 .getDescription(getVElement().getDomainModelReference(), getViewModelContext().getDomainModel()));
645:                 } catch (final NoLabelFoundException e) {
646:                         getReportService().report(new RenderingFailedReport(e));
647:                 }
648:
649:                 tableViewer.setLabelProvider(labelProvider);
650:                 tableViewer.setContentProvider(cp);
651:                 tableViewer.setInput(list);
652:
653:                 final TableColumnLayout layout = new TableColumnLayout();
654:                 composite.setLayout(layout);
655:                 layout.setColumnData(column.getColumn(), new ColumnWeightData(1, false));
656:
657:                 final VDomainModelReference dmr = getVElement().getDomainModelReference();
658:                 observableSupport = new ECPListEditingSupport(tableViewer, cellEditor, getVElement(), dmr,
659:                         list);
660:                 column.setEditingSupport(observableSupport);
661:
662:         }
663:
664:         private CellEditor createCellEditor(final EObject tempInstance, final EAttribute attribute, Table table) {
665:                 return CellEditorFactory.INSTANCE.createCellEditor(attribute, tempInstance, table, getViewModelContext());
666:         }
667:
668:         /**
669:          * Returns the attribute value which should be added as a new element.
670:          *
671:          * @param attribute the {@link EAttribute} with the data type
672:          * @return the new value
673:          * @since 1.13
674:          */
675:         protected Object getValueForNewRow(final EAttribute attribute) {
676:                 try {
677:                         Object defaultValue = attribute.getDefaultValue();
678:                         if (defaultValue == null || !attribute.getEType().isInstance(defaultValue)) {
679:                                 // Use a singular default value, but not a multiple value if that's
680:                                 // what is specified in the model, because we shouldn't add more than
681:                                 // one value
682:                                 defaultValue = attribute.getEType().getDefaultValue();
683:                         }
684:                         if (defaultValue == null) {
685:                                 defaultValue = attribute.getEType().getInstanceClass().getConstructor().newInstance();
686:                         }
687:                         return defaultValue;
688:                 } catch (final InstantiationException ex) {
689:                         getReportService().report(new AbstractReport(ex, Messages.MultiAttributeSWTRenderer_AddFailed));
690:                 } catch (final IllegalAccessException ex) {
691:                         getReportService().report(new AbstractReport(ex, Messages.MultiAttributeSWTRenderer_AddFailed));
692:                 } catch (final IllegalArgumentException ex) {
693:                         getReportService().report(new AbstractReport(ex, Messages.MultiAttributeSWTRenderer_AddFailed));
694:                 } catch (final InvocationTargetException ex) {
695:                         getReportService().report(new AbstractReport(ex, Messages.MultiAttributeSWTRenderer_AddFailed));
696:                 } catch (final NoSuchMethodException ex) {
697:                         getReportService().report(new AbstractReport(ex, Messages.MultiAttributeSWTRenderer_AddFailed));
698:                 } catch (final SecurityException ex) {
699:                         getReportService().report(new AbstractReport(ex, Messages.MultiAttributeSWTRenderer_AddFailed));
700:                 }
701:                 throw new IllegalStateException();
702:         }
703:
704:         @Override
705:         protected void applyValidation() {
706:                 Display.getDefault().asyncExec(new Runnable() {
707:
708:                         @Override
709:                         public void run() {
710:                                 if (validationIcon == null) {
711:                                         return;
712:                                 }
713:                                 if (validationIcon.isDisposed()) {
714:                                         return;
715:                                 }
716:                                 if (getVElement().getDiagnostic() == null) {
717:                                         return;
718:                                 }
719:                                 validationIcon.setImage(getValidationIcon());
720:                                 validationIcon.setToolTipText(ECPTooltipModifierHelper.modifyString(getVElement().getDiagnostic()
721:                                         .getMessage(), null));
722:                         }
723:                 });
724:         }
725:
726:         /**
727:          * {@inheritDoc}
728:          *
729:          * @see org.eclipse.emf.ecp.view.spi.core.swt.AbstractControlSWTRenderer#applyEnable()
730:          */
731:         @Override
732:         protected void applyEnable() {
733:                 super.applyEnable();
734:                 updateButtonEnabling();
735:         }
736:
737:         /**
738:          * @return
739:          */
740:         private Button getMoveDownButton() {
741:                 return downButton;
742:         }
743:
744:         /**
745:          * @return
746:          */
747:         private Button getMoveUpButton() {
748:                 return upButton;
749:         }
750:
751:         /**
752:          * @return
753:          */
754:         private Button getRemoveButton() {
755:                 return removeButton;
756:         }
757:
758:         /**
759:          * @return
760:          */
761:         private Button getAddButton() {
762:                 return addButton;
763:         }
764:
765:         /**
766:          * {@inheritDoc}
767:          */
768:         @Override
769:         public void dispose() {
770:                 if (mainComposite != null) {
771:                         mainComposite.dispose();
772:                 }
773:                 if (labelProvider != null) {
774:                         labelProvider.dispose();
775:                 }
776:                 if (composedAdapterFactory != null) {
777:                         composedAdapterFactory.dispose();
778:                 }
779:                 super.dispose();
780:         }
781:
782:         /**
783:          * Listener for the down button.
784:          *
785:          * @author David Soto Setzke
786:          * @author Johannes Faltermeier
787:          *
788:          */
789:         private final class DownButtonSelectionAdapter extends SelectionAdapter {
790:
791:                 private IObservableList list;
792:
793:                 DownButtonSelectionAdapter(IObservableList list) {
794:                         setObservableList(list);
795:                 }
796:
797:                 public void setObservableList(IObservableList list) {
798:                         this.list = list;
799:                 }
800:
801:                 @Override
802:                 public void widgetSelected(SelectionEvent e) {
803:                         final IObserving observing = IObserving.class.cast(list);
804:                         final EObject eObject = EObject.class.cast(observing.getObserved());
805:                         final EAttribute attribute = EAttribute.class.cast(list.getElementType());
806:
807:                         final int currentIndex = tableViewer.getTable().getSelectionIndex();
808:                         if (currentIndex + 1 < tableViewer.getTable().getItems().length) {
809:                                 final EditingDomain editingDomain = getEditingDomain(eObject);
810:                                 editingDomain.getCommandStack()
811:                                         .execute(new MoveCommand(editingDomain, eObject, attribute, currentIndex, currentIndex + 1));
812:                                 tableViewer.refresh();
813:                                 tableViewer.getTable().setSelection(currentIndex + 1);
814:                                 final TableItem[] selection = tableViewer.getTable().getSelection();
815:                                 if (selection.length > 0) {
816:                                         tableViewer.getTable().showItem(selection[0]);
817:                                 }
818:                         }
819:                 }
820:         }
821:
822:         /**
823:          * Listener for the up button.
824:          *
825:          * @author David Soto Setzke
826:          * @author Johannes Faltermeier
827:          *
828:          */
829:         private final class UpButtonSelectionAdapter extends SelectionAdapter {
830:
831:                 private IObservableList list;
832:
833:                 UpButtonSelectionAdapter(IObservableList list) {
834:                         setObservableList(list);
835:                 }
836:
837:                 public void setObservableList(IObservableList list) {
838:                         this.list = list;
839:                 }
840:
841:                 @Override
842:                 public void widgetSelected(SelectionEvent e) {
843:                         final IObserving observing = IObserving.class.cast(list);
844:                         final EObject eObject = EObject.class.cast(observing.getObserved());
845:                         final EAttribute attribute = EAttribute.class.cast(list.getElementType());
846:
847:                         final int currentIndex = tableViewer.getTable().getSelectionIndex();
848:                         if (currentIndex != 0) {
849:                                 final EditingDomain editingDomain = getEditingDomain(eObject);
850:
851:                                 editingDomain.getCommandStack()
852:                                         .execute(new MoveCommand(editingDomain, eObject, attribute, currentIndex, currentIndex - 1));
853:                                 tableViewer.refresh();
854:                                 tableViewer.getTable().setSelection(currentIndex - 1);
855:                                 final TableItem[] selection = tableViewer.getTable().getSelection();
856:                                 if (selection.length > 0) {
857:                                         tableViewer.getTable().showItem(selection[0]);
858:                                 }
859:                         }
860:                 }
861:         }
862:
863:         /**
864:          * Listener for the remove button.
865:          *
866:          * @author David Soto Setzke
867:          * @author Johannes Faltermeier
868:          *
869:          */
870:         private final class RemoveButtonSelectionAdapter extends SelectionAdapter {
871:
872:                 private IObservableList list;
873:
874:                 RemoveButtonSelectionAdapter(IObservableList list) {
875:                         setObservableList(list);
876:                 }
877:
878:                 public void setObservableList(IObservableList list) {
879:                         this.list = list;
880:                 }
881:
882:                 @Override
883:                 public void widgetSelected(SelectionEvent e) {
884:                         final IObserving observing = IObserving.class.cast(list);
885:                         final EObject eObject = EObject.class.cast(observing.getObserved());
886:                         final EAttribute attribute = EAttribute.class.cast(list.getElementType());
887:
888:                         final EditingDomain editingDomain = getEditingDomain(eObject);
889:                         final IStructuredSelection selection = tableViewer.getStructuredSelection();
890:                         if (!selection.isEmpty()) {
891:                                 editingDomain.getCommandStack().execute(RemoveCommand.create(editingDomain, eObject, attribute,
892:                                         selection.toList()));
893:                                 postRemove(selection);
894:                         }
895:                 }
896:         }
897:
898:         /**
899:          * Listener for the add button.
900:          *
901:          * @author David Soto Setzke
902:          * @author Johannes Faltermeier
903:          *
904:          */
905:         private final class AddButtonSelectionAdapter extends SelectionAdapter {
906:
907:                 private IObservableList list;
908:
909:                 AddButtonSelectionAdapter(IObservableList list) {
910:                         setObservableList(list);
911:                 }
912:
913:                 public void setObservableList(IObservableList list) {
914:                         this.list = list;
915:                 }
916:
917:                 @Override
918:                 public void widgetSelected(SelectionEvent event) {
919:                         try {
920:                                 final IObserving observing = IObserving.class.cast(list);
921:                                 final EObject eObject = EObject.class.cast(observing.getObserved());
922:                                 final EAttribute attribute = EAttribute.class.cast(list.getElementType());
923:
924:                                 final Object defaultValue = getValueForNewRow(attribute);
925:                                 if (defaultValue == null) {
926:                                         return;
927:                                 }
928:                                 final EditingDomain editingDomain = getEditingDomain(getViewModelContext().getDomainModel());
929:                                 editingDomain.getCommandStack()
930:                                         .execute(AddCommand.create(editingDomain, eObject, attribute, defaultValue));
931:                         } catch (final IllegalStateException ex) {
932:                                 /* logged by getValueForNewRow* already */
933:                         }
934:                 }
935:         }
936:
937:         /**
938:          * Editing support for a single element in a multi {@link EAttribute}.
939:          *
940:          * @author jfaltermeier
941:          *
942:          */
943:         private class ECPListEditingSupport extends EditingSupport {
944:
945:                 private final CellEditor cellEditor;
946:
947:                 private final VControl control;
948:
949:                 private IObservableList valueProperty;
950:
951:                 ECPListEditingSupport(ColumnViewer viewer, CellEditor cellEditor, VControl control,
952:                         VDomainModelReference domainModelReference, IObservableList valueProperty) {
953:                         super(viewer);
954:                         this.cellEditor = cellEditor;
955:                         this.control = control;
956:                         this.valueProperty = valueProperty;
957:                 }
958:
959:                 private EditingState editingState;
960:
961:                 private final ColumnViewerEditorActivationListenerHelper activationListener = new ColumnViewerEditorActivationListenerHelper();
962:
963:                 /**
964:                  * Default implementation always returns <code>true</code>.
965:                  *
966:                  * @see org.eclipse.jface.viewers.EditingSupport#canEdit(java.lang.Object)
967:                  */
968:                 @Override
969:                 protected boolean canEdit(Object element) {
970:
971:                         final boolean editable = control.isEffectivelyEnabled() && !control.isEffectivelyReadonly();
972:
973:                         if (ECPCellEditor.class.isInstance(cellEditor)) {
974:                                 ECPCellEditor.class.cast(cellEditor).setEditable(editable);
975:                                 return editable;
976:                         }
977:                         return editable;
978:                 }
979:
980:                 /**
981:                  * Default implementation always returns <code>null</code> as this will
982:                  * be handled by the Binding.
983:                  *
984:                  * @see org.eclipse.jface.viewers.EditingSupport#getValue(java.lang.Object)
985:                  */
986:                 @Override
987:                 protected Object getValue(Object element) {
988:                         // no op
989:                         return null;
990:                 }
991:
992:                 /**
993:                  * Default implementation does nothing as this will be handled by the
994:                  * Binding.
995:                  *
996:                  * @see org.eclipse.jface.viewers.EditingSupport#setValue(java.lang.Object,
997:                  * java.lang.Object)
998:                  */
999:                 @Override
1000:                 protected void setValue(Object element, Object value) {
1001:                         // no op
1002:                 }
1003:
1004:                 /**
1005:                  * Creates a {@link Binding} between the editor and the element to be
1006:                  * edited. Invokes {@link #doCreateCellEditorObservable(CellEditor)},
1007:                  * {@link #doCreateElementObservable(Object, ViewerCell)}, and then
1008:                  * {@link #createBinding(IObservableValue, IObservableValue)}.
1009:                  */
1010:                 @Override
1011:                 protected void initializeCellEditorValue(CellEditor cellEditor, ViewerCell cell) {
1012:                         final IObservableValue target = doCreateCellEditorObservable(cellEditor);
1013:                         final TableViewerRow viewerRow = (TableViewerRow) cell.getViewerRow();
1014:                         final TableItem item = (TableItem) viewerRow.getItem();
1015:                         final int index = item.getParent().indexOf(item);
1016:                         final EAttribute fakeAttribute = EcoreUtil.copy(EAttribute.class.cast(valueProperty.getElementType()));
1017:                         fakeAttribute.setUpperBound(1);
1018:                         fakeAttribute.setLowerBound(0);
1019:                         final IObservableValue model = new org.eclipse.emf.ecp.edit.internal.swt.util.ECPObservableValue(
1020:                                 valueProperty, index,
1021:                                 fakeAttribute);
1022:
1023:                         final Binding binding = createBinding(target, model);
1024:
1025:                         editingState = new EditingState(binding, target, model);
1026:
1027:                         getViewer().getColumnViewerEditor().addEditorActivationListener(activationListener);
1028:                 }
1029:
1030:                 @Override
1031:                 protected CellEditor getCellEditor(Object element) {
1032:                         return cellEditor;
1033:                 }
1034:
1035:                 protected Binding createBinding(IObservableValue target, IObservableValue model) {
1036:                         if (ECPCellEditor.class.isInstance(cellEditor)) {
1037:                                 return getDataBindingContext().bindValue(target, model,
1038:                                         ((ECPCellEditor) cellEditor).getTargetToModelStrategy(getDataBindingContext()),
1039:                                         ((ECPCellEditor) cellEditor).getModelToTargetStrategy(getDataBindingContext()));
1040:                         }
1041:                         return getDataBindingContext().bindValue(target, model);
1042:                 }
1043:
1044:                 protected IObservableValue doCreateCellEditorObservable(CellEditor cellEditor) {
1045:                         if (ECPCellEditor.class.isInstance(cellEditor)) {
1046:                                 return ((ECPCellEditor) cellEditor).getValueProperty().observe(cellEditor);
1047:                         }
1048:                         return org.eclipse.jface.databinding.swt.typed.WidgetProperties.text(SWT.FocusOut)
1049:                                 .observe(cellEditor.getControl());
1050:                 }
1051:
1052:                 @Override
1053:                 protected final void saveCellEditorValue(CellEditor cellEditor, ViewerCell cell) {
1054:                         editingState.binding.updateTargetToModel();
1055:                 }
1056:
1057:                 /**
1058:                  * A ColumnViewerEditorActivationListener to reset the cells after focus
1059:                  * lost.
1060:                  *
1061:                  * @author Eugen Neufeld
1062:                  *
1063:                  */
1064:                 private class ColumnViewerEditorActivationListenerHelper extends ColumnViewerEditorActivationListener {
1065:
1066:                         @Override
1067:                         public void afterEditorActivated(ColumnViewerEditorActivationEvent event) {
1068:                                 // do nothing
1069:                         }
1070:
1071:                         @Override
1072:                         public void afterEditorDeactivated(ColumnViewerEditorDeactivationEvent event) {
1073:                                 editingState.dispose();
1074:                                 editingState = null;
1075:
1076:                                 getViewer().getColumnViewerEditor().removeEditorActivationListener(this);
1077:                                 final ViewerCell focusCell = getViewer().getColumnViewerEditor().getFocusCell();
1078:•                                if (focusCell != null) {
1079:                                         getViewer().update(focusCell.getElement(), null);
1080:                                 }
1081:                         }
1082:
1083:                         @Override
1084:                         public void beforeEditorActivated(ColumnViewerEditorActivationEvent event) {
1085:                                 // do nothing
1086:                         }
1087:
1088:                         @Override
1089:                         public void beforeEditorDeactivated(ColumnViewerEditorDeactivationEvent event) {
1090:                                 // do nothing
1091:                         }
1092:                 }
1093:
1094:                 /**
1095:                  * Maintains references to objects that only live for the length of the
1096:                  * edit cycle.
1097:                  */
1098:                 class EditingState {
1099:                         private final IObservableValue target;
1100:
1101:                         private final IObservableValue model;
1102:
1103:                         private final Binding binding;
1104:
1105:                         EditingState(Binding binding, IObservableValue target, IObservableValue model) {
1106:                                 this.binding = binding;
1107:                                 this.target = target;
1108:                                 this.model = model;
1109:                         }
1110:
1111:                         void dispose() {
1112:                                 binding.dispose();
1113:                                 target.dispose();
1114:                                 model.dispose();
1115:                         }
1116:                 }
1117:
1118:                 public void setObservableList(IObservableList list) {
1119:                         valueProperty = list;
1120:                 }
1121:         }
1122:
1123:         /**
1124:          * {@inheritDoc}
1125:          *
1126:          * @see org.eclipse.emf.ecp.view.spi.core.swt.AbstractControlSWTRenderer#rootDomainModelChanged()
1127:          */
1128:         @Override
1129:         protected void rootDomainModelChanged() throws DatabindingFailedException {
1130:                 final IObservableList oldList = (IObservableList) getTableViewer().getInput();
1131:                 oldList.dispose();
1132:
1133:                 final IObservableList list = getEMFFormsDatabinding().getObservableList(
1134:                         getVElement().getDomainModelReference(),
1135:                         getViewModelContext().getDomainModel());
1136:                 // addRelayoutListenerIfNeeded(list, composite);
1137:                 getTableViewer().setInput(list);
1138:
1139:                 addButtonSelectionAdapter.setObservableList(list);
1140:                 removeButtonSelectionAdapter.setObservableList(list);
1141:                 upButtonSelectionAdapter.setObservableList(list);
1142:                 downButtonSelectionAdapter.setObservableList(list);
1143:                 observableSupport.setObservableList(list);
1144:         }
1145:
1146:         /**
1147:          * This is called after the selected elements were deleted so that the user can handle this removal.
1148:          *
1149:          * @param selection The {@link IStructuredSelection} of the TableViewer before deletion.
1150:          * @since 1.17
1151:          */
1152:         protected void postRemove(IStructuredSelection selection) {
1153:                 // do nothing
1154:         }
1155:
1156:         /**
1157:          * Creates an error label for the given {@link Exception}.
1158:          *
1159:          * @param parent The parent of the {@link Label}
1160:          * @param ex The {@link Exception} causing the error
1161:          * @return The error {@link Label}
1162:          * @since 1.14
1163:          */
1164:         protected Control createErrorLabel(Composite parent, final Exception ex) {
1165:                 final Label errorLabel = new Label(parent, SWT.NONE);
1166:                 errorLabel.setText(ex.getMessage());
1167:                 return errorLabel;
1168:         }
1169:
1170: }