Skip to content

Package: TableControl$ECPTableEditingSupport

TableControl$ECPTableEditingSupport

nameinstructionbranchcomplexitylinemethod
TableControl.ECPTableEditingSupport(TableControl, ColumnViewer, CellEditor, EStructuralFeature)
M: 0 C: 19
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
canEdit(Object)
M: 20 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
createBinding(IObservableValue, IObservableValue)
M: 33 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
doCreateCellEditorObservable(CellEditor)
M: 16 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
doCreateElementObservable(Object, ViewerCell)
M: 9 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
getCellEditor(Object)
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getValue(Object)
M: 2 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
initializeCellEditorValue(CellEditor, ViewerCell)
M: 40 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 9 C: 0
0%
M: 1 C: 0
0%
saveCellEditorValue(CellEditor, ViewerCell)
M: 9 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
setValue(Object, Object)
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%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2011-2015 EclipseSource Muenchen GmbH and others.
3: *
4: * All rights reserved. This program and the accompanying materials
5: * are made available under the terms of the Eclipse Public License 2.0
6: * which accompanies this distribution, and is available at
7: * https://www.eclipse.org/legal/epl-2.0/
8: *
9: * SPDX-License-Identifier: EPL-2.0
10: *
11: * Contributors:
12: * Eugen Neufeld - initial API and implementation
13: *
14: *******************************************************************************/
15: package org.eclipse.emf.ecp.edit.internal.swt.controls;
16:
17: import java.util.ArrayList;
18: import java.util.Collection;
19: import java.util.Collections;
20: import java.util.Iterator;
21: import java.util.LinkedHashMap;
22: import java.util.List;
23: import java.util.Map;
24:
25: import org.eclipse.core.databinding.Binding;
26: import org.eclipse.core.databinding.observable.list.IObservableList;
27: import org.eclipse.core.databinding.observable.map.IObservableMap;
28: import org.eclipse.core.databinding.observable.value.IObservableValue;
29: import org.eclipse.core.runtime.Assert;
30: import org.eclipse.emf.common.notify.AdapterFactory;
31: import org.eclipse.emf.common.util.Diagnostic;
32: import org.eclipse.emf.databinding.EMFProperties;
33: import org.eclipse.emf.databinding.EObjectObservableMap;
34: import org.eclipse.emf.databinding.edit.EMFEditObservables;
35: import org.eclipse.emf.ecore.EClass;
36: import org.eclipse.emf.ecore.EObject;
37: import org.eclipse.emf.ecore.EReference;
38: import org.eclipse.emf.ecore.EStructuralFeature;
39: import org.eclipse.emf.ecore.EStructuralFeature.Setting;
40: import org.eclipse.emf.ecp.edit.internal.swt.Activator;
41: import org.eclipse.emf.ecp.edit.internal.swt.table.TableColumnConfiguration;
42: import org.eclipse.emf.ecp.edit.internal.swt.table.TableControlConfiguration;
43: import org.eclipse.emf.ecp.edit.internal.swt.util.CellEditorFactory;
44: import org.eclipse.emf.ecp.edit.internal.swt.util.SWTControl;
45: import org.eclipse.emf.ecp.edit.internal.swt.util.SWTRenderingHelper;
46: import org.eclipse.emf.ecp.edit.spi.swt.table.ECPCellEditor;
47: import org.eclipse.emf.ecp.edit.spi.swt.util.ECPDialogExecutor;
48: import org.eclipse.emf.ecp.view.spi.model.VDiagnostic;
49: import org.eclipse.emf.ecp.view.spi.renderer.RenderingResultRow;
50: import org.eclipse.emf.edit.command.AddCommand;
51: import org.eclipse.emf.edit.command.RemoveCommand;
52: import org.eclipse.emf.edit.domain.EditingDomain;
53: import org.eclipse.emf.edit.provider.AdapterFactoryItemDelegator;
54: import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
55: import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
56: import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
57: import org.eclipse.emfforms.spi.localization.LocalizationServiceHelper;
58: import org.eclipse.jface.databinding.swt.typed.WidgetProperties;
59: import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
60: import org.eclipse.jface.databinding.viewers.ObservableMapCellLabelProvider;
61: import org.eclipse.jface.dialogs.IDialogConstants;
62: import org.eclipse.jface.dialogs.IDialogLabelKeys;
63: import org.eclipse.jface.dialogs.MessageDialog;
64: import org.eclipse.jface.layout.GridDataFactory;
65: import org.eclipse.jface.layout.GridLayoutFactory;
66: import org.eclipse.jface.layout.TableColumnLayout;
67: import org.eclipse.jface.resource.JFaceResources;
68: import org.eclipse.jface.viewers.CellEditor;
69: import org.eclipse.jface.viewers.CellLabelProvider;
70: import org.eclipse.jface.viewers.ColumnViewer;
71: import org.eclipse.jface.viewers.ColumnViewerEditor;
72: import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
73: import org.eclipse.jface.viewers.ColumnViewerEditorActivationListener;
74: import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
75: import org.eclipse.jface.viewers.ColumnViewerEditorDeactivationEvent;
76: import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
77: import org.eclipse.jface.viewers.ColumnWeightData;
78: import org.eclipse.jface.viewers.EditingSupport;
79: import org.eclipse.jface.viewers.IColorProvider;
80: import org.eclipse.jface.viewers.IStructuredSelection;
81: import org.eclipse.jface.viewers.TableViewer;
82: import org.eclipse.jface.viewers.TableViewerColumn;
83: import org.eclipse.jface.viewers.TableViewerEditor;
84: import org.eclipse.jface.viewers.TableViewerFocusCellManager;
85: import org.eclipse.jface.viewers.Viewer;
86: import org.eclipse.jface.viewers.ViewerCell;
87: import org.eclipse.jface.viewers.ViewerComparator;
88: import org.eclipse.swt.SWT;
89: import org.eclipse.swt.events.DisposeEvent;
90: import org.eclipse.swt.events.DisposeListener;
91: import org.eclipse.swt.events.SelectionAdapter;
92: import org.eclipse.swt.events.SelectionEvent;
93: import org.eclipse.swt.graphics.Color;
94: import org.eclipse.swt.graphics.Image;
95: import org.eclipse.swt.layout.GridLayout;
96: import org.eclipse.swt.widgets.Button;
97: import org.eclipse.swt.widgets.Composite;
98: import org.eclipse.swt.widgets.Control;
99: import org.eclipse.swt.widgets.Label;
100: import org.eclipse.swt.widgets.TableColumn;
101:
102: /**
103: * The class describing a table control.
104: *
105: * @author Eugen Neufeld
106: * @author emueller
107: */
108: // this class is not serialized
109: @Deprecated
110: public class TableControl extends SWTControl {
111:
112:         private static final String FIXED_COLUMNS = "org.eclipse.rap.rwt.fixedColumns"; //$NON-NLS-1$
113:
114:         private static final String ICON_ADD = "icons/add.png"; //$NON-NLS-1$
115:         private static final String ICONS_UNSET_REFERENCE = "icons/unset_reference.png"; //$NON-NLS-1$
116:         private static final String ICONS_UNSET_FEATURE = "icons/unset_feature.png"; //$NON-NLS-1$
117:
118:         private TableViewer tableViewer;
119:         private ComposedAdapterFactory composedAdapterFactory;
120:         private AdapterFactoryItemDelegator adapterFactoryItemDelegator;
121:         private Button unsetButton;
122:         private EClass clazz;
123:         private TableControlConfiguration tableControlConfiguration;
124:         private boolean editable = true;
125:
126:         private EReference getTableReference() {
127:                 return (EReference) getFirstStructuralFeature();
128:         }
129:
130:         /**
131:          *
132:          * @param tableControlConfiguration the {@link TableControlConfiguration} to use when creating the table
133:          */
134:         public final void setTableControlConfiguration(TableControlConfiguration tableControlConfiguration) {
135:                 this.tableControlConfiguration = tableControlConfiguration;
136:         }
137:
138:         @Override
139:         protected Binding bindValue() {
140:                 return null;
141:         }
142:
143:         /**
144:          *
145:          * {@inheritDoc}
146:          *
147:          * @see org.eclipse.emf.ecp.edit.internal.swt.util.ECPControlSWT#createControls(org.eclipse.swt.widgets.Composite)
148:          */
149:         @Override
150:         public List<RenderingResultRow<Control>> createControls(final Composite parent) {
151:                 final IItemPropertyDescriptor itemPropertyDescriptor = getItemPropertyDescriptor(getFirstSetting());
152:                 if (itemPropertyDescriptor == null) {
153:                         return null;
154:                 }
155:                 parent.addDisposeListener(new DisposeListener() {
156:
157:                         @Override
158:                         public void widgetDisposed(DisposeEvent e) {
159:                                 dispose();
160:                         }
161:                 });
162:                 final List<RenderingResultRow<Control>> list = Collections.singletonList(SWTRenderingHelper.INSTANCE
163:                         .getResultRowFactory().createRenderingResultRow(
164:                                 createControl(parent)));
165:
166:                 applyValidation(getControl().getDiagnostic());
167:                 return list;
168:
169:         }
170:
171:         @Override
172:         public Composite createControl(final Composite parent) {
173:                 mainSetting = getFirstSetting();
174:                 composedAdapterFactory = new ComposedAdapterFactory(new AdapterFactory[] {
175:                         new ReflectiveItemProviderAdapterFactory(),
176:                         new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE) });
177:
178:                 adapterFactoryItemDelegator = new AdapterFactoryItemDelegator(composedAdapterFactory);
179:
180:                 clazz = getTableReference().getEReferenceType();
181:
182:                 final Composite composite = new Composite(parent, SWT.NONE);
183:                 composite.setLayout(new GridLayout(1, false));
184:                 composite.setBackground(parent.getBackground());
185:
186:                 final Composite titleComposite = new Composite(composite, SWT.NONE);
187:                 titleComposite.setBackground(parent.getBackground());
188:                 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.BEGINNING)
189:                         .applyTo(titleComposite);
190:                 GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(false).applyTo(titleComposite);
191:
192:                 final Label label = new Label(titleComposite, SWT.NONE);
193:                 label.setBackground(parent.getBackground());
194:                 label.setText(getItemPropertyDescriptor(mainSetting).getDisplayName(null));
195:                 GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING).grab(true, false).applyTo(label);
196:
197:                 // VALIDATION
198:                 validationLabel = new Label(titleComposite, SWT.NONE);
199:                 validationLabel.setBackground(parent.getBackground());
200:                 // set the size of the label to the size of the image
201:                 GridDataFactory.fillDefaults().hint(16, 17).applyTo(validationLabel);
202:
203:                 boolean createButtons = true;
204:                 if (tableControlConfiguration != null) {
205:                         createButtons = !tableControlConfiguration.isAddRemoveDisabled();
206:                 }
207:                 if (createButtons) {
208:                         // addButtons
209:                         final Composite buttonComposite = new Composite(titleComposite, SWT.NONE);
210:                         GridDataFactory.fillDefaults().align(SWT.END, SWT.BEGINNING).grab(true, false).applyTo(buttonComposite);
211:                         int numButtons = 2;
212:
213:                         createAddRowButton(clazz, buttonComposite);
214:                         createRemoveRowButton(clazz, buttonComposite);
215:                         if (!isEmbedded() && getTableReference().isUnsettable()) {
216:                                 unsetButton = new Button(buttonComposite, SWT.PUSH);
217:                                 unsetButton.setToolTipText(getUnsetButtonTooltip());
218:                                 unsetButton.setImage(Activator.getImage(ICONS_UNSET_FEATURE));
219:                                 numButtons++;
220:                         }
221:                         GridLayoutFactory.fillDefaults().numColumns(numButtons).equalWidth(true).applyTo(buttonComposite);
222:                 }
223:                 final Composite controlComposite = new Composite(composite, SWT.NONE);
224:                 GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL,
225:                         SWT.FILL).applyTo(controlComposite);
226:                 GridLayoutFactory.fillDefaults().numColumns(1).applyTo(controlComposite);
227:
228:                 // delegate to super class
229:                 createContentControl(controlComposite);
230:
231:                 return composite;
232:         }
233:
234:         private TableViewer createTableViewer(Composite parent) {
235:                 final TableViewer tableViewer = new TableViewer(parent, SWT.MULTI | SWT.V_SCROLL | SWT.FULL_SELECTION
236:                         | SWT.BORDER);
237:                 tableViewer.getTable().setData(CUSTOM_VARIANT, "org_eclipse_emf_ecp_control_table"); //$NON-NLS-1$
238:                 tableViewer.getTable().setHeaderVisible(true);
239:                 tableViewer.getTable().setLinesVisible(true);
240:
241:                 final TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager(tableViewer,
242:                         new ECPFocusCellDrawHighlighter(tableViewer));
243:                 final ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(tableViewer) {
244:                         @Override
245:                         protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) {
246:                                 return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL
247:                                         || event.eventType == ColumnViewerEditorActivationEvent.MOUSE_CLICK_SELECTION
248:                                         || event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.CR
249:                                         || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC;
250:                         }
251:                 };
252:
253:                 TableViewerEditor.create(tableViewer, focusCellManager, actSupport, ColumnViewerEditor.TABBING_HORIZONTAL
254:                         | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR | ColumnViewerEditor.TABBING_VERTICAL
255:                         | ColumnViewerEditor.KEYBOARD_ACTIVATION);
256:
257:                 tableViewer.getTable().setData(FIXED_COLUMNS, new Integer(1));
258:                 ColumnViewerToolTipSupport.enableFor(tableViewer);
259:
260:                 return tableViewer;
261:         }
262:
263:         private void createFixedValidationStatusColumn(TableViewer tableViewer,
264:                 final List<EStructuralFeature> structuralFeatures) {
265:                 final TableViewerColumn column = TableViewerColumnBuilder
266:                         .create()
267:                         .setMoveable(false)
268:                         .setText(
269:                                 LocalizationServiceHelper.getString(getClass(),
270:                                         DepricatedControlMessageKeys.TableControl_ValidationStatusColumn))
271:                         .setWidth(80)
272:                         .build(tableViewer);
273:
274:                 column.setLabelProvider(new ValidationStatusCellLabelProvider(structuralFeatures));
275:         }
276:
277:         private EObject getInstanceOf(EClass clazz) {
278:                 return clazz.getEPackage().getEFactoryInstance().create(clazz);
279:         }
280:
281:         /*
282:          * (non-Javadoc)
283:          * @see
284:          * org.eclipse.emf.ecp.edit.internal.swt.util.SWTControl#fillControlComposite(org.eclipse.swt.widgets.Composite)
285:          */
286:         @Override
287:         protected void fillControlComposite(Composite parent) {
288:                 final Composite composite = new Composite(parent, SWT.NONE);
289:                 GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).hint(1, 200).applyTo(composite);
290:                 tableViewer = createTableViewer(composite);
291:
292:                 final ObservableListContentProvider cp = new ObservableListContentProvider();
293:                 final EObject tempInstance = getInstanceOf(clazz);
294:                 final ECPTableViewerComparator comparator = new ECPTableViewerComparator();
295:                 tableViewer.setComparator(comparator);
296:                 int columnNumber = 0;
297:                 final Map<EStructuralFeature, Boolean> readOnlyConfig = createReadOnlyConfig(clazz);
298:                 final List<EStructuralFeature> structuralFeatures = new ArrayList<EStructuralFeature>();
299:                 structuralFeatures.addAll(readOnlyConfig.keySet());
300:                 if (!getControl().isReadonly()) {
301:                         createFixedValidationStatusColumn(tableViewer, structuralFeatures);
302:                 }
303:
304:                 for (final EStructuralFeature feature : structuralFeatures) {
305:                         final IItemPropertyDescriptor itemPropertyDescriptor = adapterFactoryItemDelegator.getPropertyDescriptor(
306:                                 tempInstance, feature);
307:                         if (itemPropertyDescriptor == null) {
308:                                 // if we can't render because no edit information is available, do nothing
309:                                 continue;
310:                         }
311:
312:                         final CellEditor cellEditor = createCellEditor(tempInstance, feature);
313:                         final TableViewerColumn column = TableViewerColumnBuilder
314:                                 .create()
315:                                 .setText(itemPropertyDescriptor.getDisplayName(null))
316:                                 .setToolTipText(itemPropertyDescriptor.getDescription(null))
317:                                 .setResizable(true)
318:                                 .setMoveable(false)
319:                                 .setStyle(noStyle())
320:                                 .setData("width", //$NON-NLS-1$
321:                                         ECPCellEditor.class.isInstance(cellEditor) ? ECPCellEditor.class.cast(cellEditor)
322:                                                 .getColumnWidthWeight() : 100)
323:                                 .build(tableViewer);
324:
325:                         column.setLabelProvider(new ECPCellLabelProvider(feature, cellEditor,
326:                                 feature.isMany() ? new EObjectObservableMap(cp.getKnownElements(), feature)
327:                                         : EMFProperties.value(feature).observeDetail(cp.getKnownElements())));
328:                         column.getColumn().addSelectionListener(getSelectionAdapter(comparator, column.getColumn(), columnNumber));
329:
330:                         if (!isReadOnlyFeature(readOnlyConfig, feature)) {
331:                                 // remove if no editing needed
332:                                 final EditingSupport observableSupport = new ECPTableEditingSupport(tableViewer, cellEditor, feature);
333:                                 column.setEditingSupport(observableSupport);
334:                         }
335:                         columnNumber++;
336:                 }
337:                 tableViewer.setContentProvider(cp);
338:                 final IObservableList list = EMFEditObservables.observeList(getEditingDomain(mainSetting),
339:                         mainSetting.getEObject(), mainSetting.getEStructuralFeature());
340:                 tableViewer.setInput(list);
341:
342:                 // IMPORTANT:
343:                 // - the minimumWidth and (non)resizable settings of the ColumnWeightData are not supported properly
344:                 // - the layout stops resizing columns that have been resized manually by the user (this could be considered a
345:                 // feature though)
346:                 final TableColumnLayout layout = new TableColumnLayout();
347:                 composite.setLayout(layout);
348:                 for (int i = 0; i < tableViewer.getTable().getColumns().length; i++) {
349:                         final Integer storedValue = (Integer) tableViewer.getTable().getColumns()[i].getData("width"); //$NON-NLS-1$
350:                         layout.setColumnData(tableViewer.getTable().getColumns()[i], new ColumnWeightData(storedValue == null ? 50
351:                                 : storedValue));
352:                 }
353:         }
354:
355:         private CellEditor createCellEditor(final EObject tempInstance, final EStructuralFeature feature) {
356:                 return CellEditorFactory.INSTANCE.getCellEditor(feature,
357:                         tempInstance, tableViewer.getTable(), getViewModelContext());
358:         }
359:
360:         private static boolean isReadOnlyFeature(Map<EStructuralFeature, Boolean> readOnlyConfig,
361:                 EStructuralFeature feature) {
362:                 if (readOnlyConfig != null) {
363:                         final Boolean isReadOnly = readOnlyConfig.get(feature);
364:                         if (isReadOnly != null) {
365:                                 return isReadOnly;
366:                         }
367:                 }
368:                 return false;
369:         }
370:
371:         private Map<EStructuralFeature, Boolean> createReadOnlyConfig(EClass clazz) {
372:                 final Map<EStructuralFeature, Boolean> readOnlyConfig = new LinkedHashMap<EStructuralFeature, Boolean>();
373:                 if (tableControlConfiguration != null) {
374:                         for (final TableColumnConfiguration tcc : tableControlConfiguration.getColumns()) {
375:                                 readOnlyConfig.put(tcc.getColumnAttribute(), tcc.isReadOnly());
376:                         }
377:                 } else {
378:                         for (final EStructuralFeature feature : clazz.getEStructuralFeatures()) {
379:                                 readOnlyConfig.put(feature, Boolean.FALSE);
380:                         }
381:                 }
382:                 return readOnlyConfig;
383:         }
384:
385:         private int noStyle() {
386:                 return SWT.NONE;
387:         }
388:
389:         @Override
390:         protected Button getCustomUnsetButton() {
391:                 return unsetButton;
392:         }
393:
394:         private SelectionAdapter getSelectionAdapter(final ECPTableViewerComparator comparator, final TableColumn column,
395:                 final int index) {
396:                 final SelectionAdapter selectionAdapter = new SelectionAdapter() {
397:                         @Override
398:                         public void widgetSelected(SelectionEvent e) {
399:                                 comparator.setColumn(index);
400:                                 final int dir = comparator.getDirection();
401:                                 tableViewer.getTable().setSortDirection(dir);
402:                                 tableViewer.getTable().setSortColumn(column);
403:                                 tableViewer.refresh();
404:                         }
405:                 };
406:                 return selectionAdapter;
407:         }
408:
409:         private Button removeButton;
410:
411:         private void createRemoveRowButton(EClass clazz, final Composite buttonComposite) {
412:                 removeButton = new Button(buttonComposite, SWT.None);
413:                 final Image image = Activator.getImage(ICONS_UNSET_REFERENCE);
414:                 removeButton.setImage(image);
415:                 removeButton.setToolTipText(LocalizationServiceHelper.getString(getClass(),
416:                         DepricatedControlMessageKeys.TableControl_RemoveSelected)
417:                         + clazz.getInstanceClass().getSimpleName());
418:                 removeButton.addSelectionListener(new SelectionAdapter() {
419:                         /*
420:                          * (non-Javadoc)
421:                          * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
422:                          */
423:                         @Override
424:                         public void widgetSelected(SelectionEvent e) {
425:                                 final IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection();
426:
427:                                 if (selection == null || selection.getFirstElement() == null) {
428:                                         return;
429:                                 }
430:
431:                                 final List<EObject> deletionList = new ArrayList<EObject>();
432:                                 final Iterator<?> iterator = selection.iterator();
433:
434:                                 while (iterator.hasNext()) {
435:                                         deletionList.add((EObject) iterator.next());
436:                                 }
437:
438:                                 deleteRowUserConfirmDialog(deletionList);
439:
440:                         }
441:                 });
442:
443:                 final List<?> containments = (List<?>) mainSetting.get(true);
444:                 if (containments.size() <= getTableReference().getLowerBound()) {
445:                         removeButton.setEnabled(false);
446:                 }
447:         }
448:
449:         /**
450:          * This method shows a user confirmation dialog when the user attempts to delete a row in the table.
451:          *
452:          * @param deletionList the list of selected EObjects to delete
453:          */
454:         protected void deleteRowUserConfirmDialog(final List<EObject> deletionList) {
455:                 final MessageDialog dialog = new MessageDialog(
456:                         tableViewer.getTable().getShell(),
457:                         LocalizationServiceHelper.getString(getClass(), DepricatedControlMessageKeys.TableControl_Delete),
458:                         null,
459:                         LocalizationServiceHelper.getString(getClass(), DepricatedControlMessageKeys.TableControl_DeleteAreYouSure),
460:                         MessageDialog.CONFIRM, new String[] {
461:                                 JFaceResources.getString(IDialogLabelKeys.YES_LABEL_KEY),
462:                                 JFaceResources.getString(IDialogLabelKeys.NO_LABEL_KEY) },
463:                         0);
464:
465:                 new ECPDialogExecutor(dialog) {
466:
467:                         @Override
468:                         public void handleResult(int codeResult) {
469:                                 if (codeResult == IDialogConstants.CANCEL_ID) {
470:                                         return;
471:                                 }
472:
473:                                 deleteRows(deletionList);
474:
475:                                 final List<?> containments = (List<?>) mainSetting.get(true);
476:                                 if (containments.size() < getTableReference().getUpperBound()) {
477:                                         addButton.setEnabled(true);
478:                                 }
479:                                 if (containments.size() <= getTableReference().getLowerBound()) {
480:                                         removeButton.setEnabled(false);
481:                                 }
482:                         }
483:                 }.execute();
484:         }
485:
486:         /**
487:          * This is called by {@link #deleteRowUserConfirmDialog(List)} after the user confirmed to delete the selected
488:          * elements.
489:          *
490:          * @param deletionList the list of {@link EObject EObjects} to delete
491:          */
492:         protected void deleteRows(List<EObject> deletionList) {
493:                 final EditingDomain editingDomain = getEditingDomain(mainSetting);
494:                 final EObject modelElement = mainSetting.getEObject();
495:                 editingDomain.getCommandStack().execute(
496:                         RemoveCommand.create(editingDomain, modelElement, getTableReference(), deletionList));
497:         }
498:
499:         /**
500:          * This method is called to add a new entry in the domain model and thus to create a new row in the table. The
501:          * element to create is defined by the provided class.
502:          * You can override this method but you have to call super nonetheless.
503:          *
504:          * @param clazz the {@link EClass} defining the EObject to create
505:          */
506:         protected void addRow(EClass clazz) {
507:                 final EObject modelElement = mainSetting.getEObject();
508:                 final EObject instance = clazz.getEPackage().getEFactoryInstance().create(clazz);
509:
510:                 final EditingDomain editingDomain = getEditingDomain(mainSetting);
511:                 editingDomain.getCommandStack().execute(
512:                         AddCommand.create(editingDomain, modelElement, getTableReference(), instance));
513:
514:         }
515:
516:         private Button addButton;
517:         private Setting mainSetting;
518:
519:         private boolean isDisposing;
520:
521:         private void createAddRowButton(final EClass clazz, final Composite buttonComposite) {
522:                 addButton = new Button(buttonComposite, SWT.None);
523:                 final Image image = Activator.getImage(ICON_ADD);
524:                 addButton.setImage(image);
525:                 addButton.setToolTipText(LocalizationServiceHelper.getString(getClass(),
526:                         DepricatedControlMessageKeys.TableControl_AddInstanceOf) + clazz.getInstanceClass().getSimpleName());
527:                 addButton.addSelectionListener(new SelectionAdapter() {
528:
529:                         /*
530:                          * (non-Javadoc)
531:                          * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
532:                          */
533:                         @Override
534:                         public void widgetSelected(SelectionEvent e) {
535:                                 addRow(clazz);
536:
537:                                 final List<?> containments = (List<?>) mainSetting.get(true);
538:                                 if (getTableReference().getUpperBound() != -1
539:                                         && containments.size() >= getTableReference().getUpperBound()) {
540:                                         addButton.setEnabled(false);
541:                                 }
542:                                 if (containments.size() > getTableReference().getLowerBound()) {
543:                                         removeButton.setEnabled(true);
544:                                 }
545:                         }
546:                 });
547:
548:                 final List<?> containments = (List<?>) mainSetting.get(true);
549:                 if (getTableReference().getUpperBound() != -1
550:                         && containments.size() >= getTableReference().getUpperBound()) {
551:                         addButton.setEnabled(false);
552:                 }
553:         }
554:
555:         /**
556:          * {@inheritDoc}
557:          */
558:         @Override
559:         public void dispose() {
560:                 isDisposing = true;
561:                 super.dispose();
562:                 composedAdapterFactory.dispose();
563:                 mainSetting = null;
564:                 adapterFactoryItemDelegator = null;
565:                 composedAdapterFactory = null;
566:                 isDisposing = false;
567:         }
568:
569:         /**
570:          * {@inheritDoc}
571:          *
572:          * @see org.eclipse.emf.ecp.edit.spi.ECPAbstractControl#applyValidation(org.eclipse.emf.ecp.view.spi.model.VDiagnostic)
573:          */
574:         @Override
575:         protected void applyValidation(VDiagnostic diagnostic) {
576:
577:                 if (validationLabel == null || validationLabel.isDisposed()) {
578:                         return;
579:                 }
580:                 if (diagnostic != null) {
581:                         final Image image = getValidationIcon(diagnostic.getHighestSeverity());
582:                         validationLabel.setImage(image);
583:                         validationLabel.setToolTipText(diagnostic.getMessage());
584:                         for (final Object object : (Collection<?>) mainSetting.get(true)) {
585:                                 tableViewer.update(object, null);
586:                         }
587:                 }
588:         }
589:
590:         // /**
591:         // * {@inheritDoc}
592:         // *
593:         // * @deprecated
594:         // */
595:         // @Deprecated
596:         // @Override
597:         // public void resetValidation() {
598:         // if (validationLabel == null || validationLabel.isDisposed()) {
599:         // return;
600:         // }
601:         // validationLabel.setToolTipText(""); //$NON-NLS-1$
602:         // validationLabel.setImage(null);
603:         // tableViewer.refresh();
604:         // }
605:         // /**
606:         // * {@inheritDoc}
607:         // *
608:         // * @deprecated
609:         // */
610:         // @Deprecated
611:         // @Override
612:         // public void handleValidation(Diagnostic diagnostic) {
613:         // if (diagnostic.getData().isEmpty()) {
614:         // return;
615:         // }
616:         // final Image image = getValidationIcon(diagnostic.getSeverity());
617:         // validationLabel.setImage(image);
618:         // validationLabel.setToolTipText(getTableTooltipMessage(diagnostic));
619:         // final EObject object = (EObject) diagnostic.getData().get(0);
620:         // tableViewer.update(object, null);
621:         // }
622:
623:         /**
624:          * Returns the message of the validation tool tip shown in the table header.
625:          *
626:          * @param diagnostic the {@link Diagnostic} to extract the message from
627:          * @return the message
628:          */
629:         protected String getTableTooltipMessage(Diagnostic diagnostic) {
630:                 return diagnostic.getMessage();
631:         }
632:
633:         /**
634:          * Returns the message of the validation tool tip shown in the row.
635:          *
636:          * @param vDiagnostic the {@link VDiagnostic} to get the message from
637:          * @return the message
638:          */
639:         protected String getRowTooltipMessage(VDiagnostic vDiagnostic) {
640:                 return vDiagnostic.getMessage();
641:         }
642:
643:         /**
644:          * Returns the message of the validation tool tip shown in the cell.
645:          *
646:          * @param vDiagnostic the {@link VDiagnostic} to get the message from
647:          * @return the message
648:          */
649:         protected String getCellTooltipMessage(VDiagnostic vDiagnostic) {
650:                 if (vDiagnostic == null) {
651:                         return null;
652:                 }
653:                 if (vDiagnostic.getDiagnostics().size() == 0) {
654:                         return vDiagnostic.getMessage();
655:                 }
656:                 final Diagnostic diagnostic = (Diagnostic) vDiagnostic.getDiagnostics().get(0);
657:                 Diagnostic reason = diagnostic;
658:                 if (diagnostic.getChildren() != null && diagnostic.getChildren().size() != 0) {
659:                         reason = diagnostic.getChildren().get(0);
660:                 }
661:                 return reason.getMessage();
662:         }
663:
664:         /**
665:          * {@inheritDoc}
666:          *
667:          * @deprecated
668:          */
669:         @Deprecated
670:         @Override
671:         public void setEditable(boolean isEditable) {
672:                 if (addButton != null) {
673:                         addButton.setVisible(isEditable);
674:                 }
675:                 if (removeButton != null) {
676:                         removeButton.setVisible(isEditable);
677:                 }
678:                 editable = isEditable;
679:         }
680:
681:         /**
682:          * @author Jonas
683:          *
684:          */
685:         private final class ValidationStatusCellLabelProvider extends CellLabelProvider {
686:                 private final List<EStructuralFeature> structuralFeatures;
687:
688:                 /**
689:                  * @param structuralFeatures
690:                  */
691:                 private ValidationStatusCellLabelProvider(List<EStructuralFeature> structuralFeatures) {
692:                         this.structuralFeatures = structuralFeatures;
693:                 }
694:
695:                 @Override
696:                 public void update(ViewerCell cell) {
697:                         Integer mostSevere = Diagnostic.OK;
698:                         final VDiagnostic vDiagnostic = getControl().getDiagnostic();
699:                         // for (final Object diagObject : vDiagnostic.getDiagnostics()) {
700:                         // final Diagnostic diagnostic = (Diagnostic) diagObject;
701:                         // if (diagnostic.getData().size() == 0) {
702:                         // continue;
703:                         // }
704:                         // if (diagnostic.getData().get(0).equals(cell.getElement())) {
705:                         // final int currentSeverity = diagnostic.getSeverity();
706:                         // if (currentSeverity > mostSevere) {
707:                         // mostSevere = currentSeverity;
708:                         // }
709:                         // }
710:                         // }
711:                         final List<Diagnostic> diagnostics = vDiagnostic.getDiagnostics((EObject) cell.getElement());
712:                         if (diagnostics.size() != 0) {
713:                                 mostSevere = diagnostics.get(0).getSeverity();
714:                         }
715:                         cell.setImage(getValidationIcon(mostSevere));
716:                 }
717:
718:                 @Override
719:                 public String getToolTipText(Object element) {
720:                         final StringBuffer tooltip = new StringBuffer();
721:                         final VDiagnostic vDiagnostic = getControl().getDiagnostic();
722:                         // for (final Object diagObject : vDiagnostic.getDiagnostics()) {
723:                         // final Diagnostic diagnostic = (Diagnostic) diagObject;
724:                         // if (diagnostic.getData().size() < 2) {
725:                         // continue;
726:                         // }
727:                         // if (diagnostic.getSeverity() == Diagnostic.OK) {
728:                         // continue;
729:                         // }
730:                         // if (diagnostic.getData().get(0).equals(element)
731:                         // && structuralFeatures.contains(diagnostic.getData().get(1))) {
732:                         // if (tooltip.length() > 0) {
733:                         // tooltip.append("\n"); //$NON-NLS-1$
734:                         // }
735:                         // tooltip.append(diagnostic.getMessage());
736:                         // }
737:                         // }
738:
739:                         final List<Diagnostic> diagnostics = vDiagnostic.getDiagnostics((EObject) element);
740:                         for (final Diagnostic diagnostic : diagnostics) {
741:                                 if (tooltip.length() > 0) {
742:                                         tooltip.append("\n"); //$NON-NLS-1$
743:                                 }
744:                                 tooltip.append(diagnostic.getMessage());
745:                         }
746:
747:                         return tooltip.toString();
748:                 }
749:         }
750:
751:         /**
752:          * The {@link ViewerComparator} for this table which allows 3 states for sort order:
753:          * none, up and down.
754:          *
755:          * @author Eugen Neufeld
756:          *
757:          */
758:         private class ECPTableViewerComparator extends ViewerComparator {
759:                 private int propertyIndex;
760:                 private static final int NONE = 0;
761:                 private int direction = NONE;
762:
763:                 ECPTableViewerComparator() {
764:                         propertyIndex = 0;
765:                         direction = NONE;
766:                 }
767:
768:                 public int getDirection() {
769:                         switch (direction) {
770:                         case 0:
771:                                 return SWT.NONE;
772:                         case 1:
773:                                 return SWT.UP;
774:                         case 2:
775:                                 return SWT.DOWN;
776:                         default:
777:                                 return SWT.NONE;
778:                         }
779:
780:                 }
781:
782:                 public void setColumn(int column) {
783:                         if (column == propertyIndex) {
784:                                 // Same column as last sort; toggle the direction
785:                                 direction = (direction + 1) % 3;
786:                         } else {
787:                                 // New column; do an ascending sort
788:                                 propertyIndex = column;
789:                                 direction = 1;
790:                         }
791:                 }
792:
793:                 @Override
794:                 public int compare(Viewer viewer, Object e1, Object e2) {
795:                         if (direction == 0) {
796:                                 return 0;
797:                         }
798:                         int rc = 0;
799:                         final EObject object1 = (EObject) e1;
800:                         final EObject object2 = (EObject) e2;
801:                         final EStructuralFeature feat1 = object1.eClass().getEAllStructuralFeatures().get(propertyIndex);
802:                         final EStructuralFeature feat2 = object2.eClass().getEAllStructuralFeatures().get(propertyIndex);
803:
804:                         final Object value1 = object1.eGet(feat1);
805:                         final Object value2 = object2.eGet(feat2);
806:
807:                         if (value1 == null) {
808:                                 rc = 1;
809:                         } else if (value2 == null) {
810:                                 rc = -1;
811:                         } else {
812:                                 rc = value1.toString().compareTo(value2.toString());
813:                         }
814:                         // If descending order, flip the direction
815:                         if (direction == 2) {
816:                                 rc = -rc;
817:                         }
818:                         return rc;
819:                 }
820:         }
821:
822:         /**
823:          * ECP specficic cell label provider that does also implement {@link IColorProvider} in
824:          * order to correctly.
825:          *
826:          * @author emueller
827:          *
828:          */
829:         public class ECPCellLabelProvider extends ObservableMapCellLabelProvider implements IColorProvider {
830:
831:                 private final EStructuralFeature feature;
832:                 private final CellEditor cellEditor;
833:
834:                 /**
835:                  * Constructor.
836:                  *
837:                  * @param feature
838:                  * the {@link EStructuralFeature} the cell is bound to
839:                  * @param cellEditor
840:                  * the {@link CellEditor} instance
841:                  * @param attributeMap
842:                  * an {@link IObservableMap} instance that is passed to the {@link ObservableMapCellLabelProvider}
843:                  */
844:                 public ECPCellLabelProvider(EStructuralFeature feature, CellEditor cellEditor, IObservableMap attributeMap) {
845:                         super(attributeMap);
846:                         this.feature = feature;
847:                         this.cellEditor = cellEditor;
848:                 }
849:
850:                 /**
851:                  * {@inheritDoc}
852:                  *
853:                  * @see org.eclipse.jface.viewers.CellLabelProvider#getToolTipText(java.lang.Object)
854:                  */
855:                 @Override
856:                 public String getToolTipText(Object element) {
857:                         final EObject domainObject = (EObject) element;
858:
859:                         final StringBuffer tooltip = new StringBuffer();
860:                         final VDiagnostic vDiagnostic = getControl().getDiagnostic();
861:                         final List<Diagnostic> diagnostics = vDiagnostic.getDiagnostic(domainObject, feature);
862:                         for (final Diagnostic diagnostic : diagnostics) {
863:                                 if (tooltip.length() > 0) {
864:                                         tooltip.append("\n"); //$NON-NLS-1$
865:                                 }
866:                                 tooltip.append(diagnostic.getMessage());
867:                         }
868:                         return tooltip.toString();
869:
870:                         // final VDiagnostic vDiagnostic = getControl().getDiagnostic();
871:                         // for (final Object diagObject : vDiagnostic.getDiagnostics()) {
872:                         // final Diagnostic diagnostic = (Diagnostic) diagObject;
873:                         // if (diagnostic.getData().size() < 2) {
874:                         // continue;
875:                         // }
876:                         // if (diagnostic.getData().get(0).equals(element) && diagnostic.getData().get(1).equals(feature)) {
877:                         //
878:                         // if (diagnostic.getChildren() != null && diagnostic.getChildren().size() != 0) {
879:                         // boolean childrenUsefull = false;
880:                         // for (final Diagnostic diagnostic2 : diagnostic.getChildren()) {
881:                         // if (diagnostic2.getSeverity() != Diagnostic.OK) {
882:                         // if (tooltip.length() > 0) {
883:                         // tooltip.append("\n"); //$NON-NLS-1$
884:                         // }
885:                         // tooltip.append(diagnostic2.getMessage());
886:                         // childrenUsefull = true;
887:                         // }
888:                         // }
889:                         // if (!childrenUsefull) {
890:                         // if (tooltip.length() > 0) {
891:                         // tooltip.append("\n"); //$NON-NLS-1$
892:                         // }
893:                         // tooltip.append(diagnostic.getMessage());
894:                         // }
895:                         // } else {
896:                         // if (tooltip.length() > 0) {
897:                         // tooltip.append("\n"); //$NON-NLS-1$
898:                         // }
899:                         // tooltip.append(diagnostic.getMessage());
900:                         // }
901:                         // }
902:                         // }
903:                         // if (tooltip.length() != 0) {
904:                         // return tooltip.toString();
905:                         // }
906:                         // final Object value = ((EObject) element).eGet(feature);
907:                         // if (value == null) {
908:                         // return null;
909:                         // }
910:                         // return String.valueOf(value);
911:                 }
912:
913:                 @Override
914:                 public void update(ViewerCell cell) {
915:                         final EObject element = (EObject) cell.getElement();
916:                         final Object value = attributeMaps[0].get(element);
917:
918:                         if (ECPCellEditor.class.isInstance(cellEditor)) {
919:                                 final ECPCellEditor ecpCellEditor = (ECPCellEditor) cellEditor;
920:                                 final String text = ecpCellEditor.getFormatedString(value);
921:                                 cell.setText(text == null ? "" : text); //$NON-NLS-1$
922:                                 cell.setImage(ecpCellEditor.getImage(value));
923:                         } else {
924:                                 cell.setText(value == null ? "" : value.toString()); //$NON-NLS-1$
925:                                 cell.getControl().setData(CUSTOM_VARIANT, "org_eclipse_emf_ecp_edit_cellEditor_string"); //$NON-NLS-1$
926:                         }
927:
928:                         cell.setBackground(getBackground(element));
929:                 }
930:
931:                 /**
932:                  * {@inheritDoc}
933:                  *
934:                  * @see org.eclipse.jface.viewers.IColorProvider#getForeground(java.lang.Object)
935:                  */
936:                 @Override
937:                 public Color getForeground(Object element) {
938:                         return null;
939:                 }
940:
941:                 /**
942:                  * {@inheritDoc}
943:                  *
944:                  * @see org.eclipse.jface.viewers.IColorProvider#getBackground(java.lang.Object)
945:                  */
946:                 @Override
947:                 public Color getBackground(Object element) {
948:                         if (isDisposing) {
949:                                 return null;
950:                         }
951:
952:                         final Integer mostSevere = Diagnostic.OK;
953:                         final VDiagnostic vDiagnostic = getControl().getDiagnostic();
954:                         // for (final Object diagObject : vDiagnostic.getDiagnostics()) {
955:                         // final Diagnostic diagnostic = (Diagnostic) diagObject;
956:                         // if (diagnostic.getData().size() < 2) {
957:                         // continue;
958:                         // }
959:                         // if (diagnostic.getData().get(0).equals(element) && diagnostic.getData().get(1).equals(feature)) {
960:                         // final int currentSeverity = diagnostic.getSeverity();
961:                         // if (currentSeverity > mostSevere) {
962:                         // mostSevere = currentSeverity;
963:                         // }
964:                         // }
965:                         // }
966:                         final List<Diagnostic> diagnostic = vDiagnostic.getDiagnostic((EObject) element, feature);
967:                         return getValidationBackgroundColor(diagnostic.size() == 0 ? Diagnostic.OK
968:                                 : diagnostic.get(0)
969:                                         .getSeverity());
970:                 }
971:         }
972:
973:         /*
974:          * (non-Javadoc)
975:          * @see org.eclipse.emf.ecp.edit.internal.swt.util.SWTControl#getUnsetLabelText()
976:          */
977:         @Override
978:         protected String getUnsetLabelText() {
979:                 return LocalizationServiceHelper.getString(getClass(),
980:                         DepricatedControlMessageKeys.TableControl_NotSetClickToSet);
981:         }
982:
983:         /*
984:          * (non-Javadoc)
985:          * @see org.eclipse.emf.ecp.edit.internal.swt.util.SWTControl#getUnsetButtonTooltip()
986:          */
987:         @Override
988:         protected String getUnsetButtonTooltip() {
989:                 return LocalizationServiceHelper.getString(getClass(), DepricatedControlMessageKeys.TableControl_Unset);
990:         }
991:
992:         /*
993:          * (non-Javadoc)
994:          * @see org.eclipse.emf.ecp.edit.internal.swt.util.SWTControl#getControlForTooltip()
995:          */
996:         @Override
997:         protected Control[] getControlsForTooltip() {
998:                 // return new Control[] { tableViewer.getControl() };
999:                 return new Control[0];
1000:         }
1001:
1002:         /**
1003:          * {@inheritDoc}
1004:          *
1005:          * @deprecated
1006:          */
1007:         @Override
1008:         @Deprecated
1009:         public boolean showLabel() {
1010:                 return false;
1011:         }
1012:
1013:         /**
1014:          * Implementation of the {@link EditingSupport} for the generic ECP Table.
1015:          *
1016:          * @author Eugen Neufeld
1017:          *
1018:          */
1019:         class ECPTableEditingSupport extends EditingSupport {
1020:
1021:                 private final CellEditor cellEditor;
1022:
1023:                 private final EStructuralFeature cellFeature;
1024:
1025:                 /**
1026:                  * @param viewer
1027:                  */
1028:                 ECPTableEditingSupport(ColumnViewer viewer, CellEditor cellEditor, EStructuralFeature feature) {
1029:                         super(viewer);
1030:                         this.cellEditor = cellEditor;
1031:                         cellFeature = feature;
1032:                 }
1033:
1034:                 private EditingState editingState;
1035:
1036:                 private final ColumnViewerEditorActivationListenerHelper activationListener = new ColumnViewerEditorActivationListenerHelper();
1037:
1038:                 /**
1039:                  * Default implementation always returns <code>true</code>.
1040:                  *
1041:                  * @see org.eclipse.jface.viewers.EditingSupport#canEdit(java.lang.Object)
1042:                  */
1043:                 @Override
1044:                 protected boolean canEdit(Object element) {
1045:•                        if (ECPCellEditor.class.isInstance(cellEditor)) {
1046:                                 ECPCellEditor.class.cast(cellEditor).setEditable(editable);
1047:                                 return true;
1048:                         }
1049:                         return editable;
1050:                 }
1051:
1052:                 /**
1053:                  * Default implementation always returns <code>null</code> as this will be
1054:                  * handled by the Binding.
1055:                  *
1056:                  * @see org.eclipse.jface.viewers.EditingSupport#getValue(java.lang.Object)
1057:                  */
1058:                 @Override
1059:                 protected Object getValue(Object element) {
1060:                         // no op
1061:                         return null;
1062:                 }
1063:
1064:                 /**
1065:                  * Default implementation does nothing as this will be handled by the
1066:                  * Binding.
1067:                  *
1068:                  * @see org.eclipse.jface.viewers.EditingSupport#setValue(java.lang.Object, java.lang.Object)
1069:                  */
1070:                 @Override
1071:                 protected void setValue(Object element, Object value) {
1072:                         // no op
1073:                 }
1074:
1075:                 /**
1076:                  * Creates a {@link Binding} between the editor and the element to be
1077:                  * edited. Invokes {@link #doCreateCellEditorObservable(CellEditor)},
1078:                  * {@link #doCreateElementObservable(Object, ViewerCell)}, and then
1079:                  * {@link #createBinding(IObservableValue, IObservableValue)}.
1080:                  */
1081:                 @Override
1082:                 protected void initializeCellEditorValue(CellEditor cellEditor, ViewerCell cell) {
1083:
1084:                         final IObservableValue target = doCreateCellEditorObservable(cellEditor);
1085:                         Assert.isNotNull(target, "doCreateCellEditorObservable(...) did not return an observable"); //$NON-NLS-1$
1086:
1087:                         final IObservableValue model = doCreateElementObservable(cell.getElement(), cell);
1088:                         Assert.isNotNull(model, "doCreateElementObservable(...) did not return an observable"); //$NON-NLS-1$
1089:
1090:                         final Binding binding = createBinding(target, model);
1091:
1092:                         Assert.isNotNull(binding, "createBinding(...) did not return a binding"); //$NON-NLS-1$
1093:
1094:                         editingState = new EditingState(binding, target, model);
1095:
1096:                         getViewer().getColumnViewerEditor().addEditorActivationListener(activationListener);
1097:                 }
1098:
1099:                 @Override
1100:                 protected CellEditor getCellEditor(Object element) {
1101:                         return cellEditor;
1102:                 }
1103:
1104:                 protected Binding createBinding(IObservableValue target, IObservableValue model) {
1105:•                        if (ECPCellEditor.class.isInstance(cellEditor)) {
1106:                                 return getDataBindingContext().bindValue(target, model,
1107:                                         ((ECPCellEditor) cellEditor).getTargetToModelStrategy(getDataBindingContext()),
1108:                                         ((ECPCellEditor) cellEditor).getModelToTargetStrategy(getDataBindingContext()));
1109:                         }
1110:                         return getDataBindingContext().bindValue(target, model);
1111:                 }
1112:
1113:                 protected IObservableValue doCreateElementObservable(Object element, ViewerCell cell) {
1114:                         return EMFEditObservables.observeValue(getEditingDomain(),
1115:                                 (EObject) element, cellFeature);
1116:                 }
1117:
1118:                 protected IObservableValue doCreateCellEditorObservable(CellEditor cellEditor) {
1119:•                        if (ECPCellEditor.class.isInstance(cellEditor)) {
1120:                                 return ((ECPCellEditor) cellEditor).getValueProperty().observe(cellEditor);
1121:                         }
1122:                         return WidgetProperties.text(SWT.FocusOut).observe(cellEditor.getControl());
1123:                 }
1124:
1125:                 @Override
1126:                 protected final void saveCellEditorValue(CellEditor cellEditor, ViewerCell cell) {
1127:•                        if (editingState.isUpdateNeeded()) {
1128:                                 editingState.binding.updateTargetToModel();
1129:                         }
1130:                 }
1131:
1132:                 class ColumnViewerEditorActivationListenerHelper extends ColumnViewerEditorActivationListener {
1133:
1134:                         @Override
1135:                         public void afterEditorActivated(ColumnViewerEditorActivationEvent event) {
1136:                                 // do nothing
1137:                         }
1138:
1139:                         @Override
1140:                         public void afterEditorDeactivated(ColumnViewerEditorDeactivationEvent event) {
1141:                                 editingState.dispose();
1142:                                 editingState = null;
1143:
1144:                                 getViewer().getColumnViewerEditor().removeEditorActivationListener(this);
1145:                                 final ViewerCell focusCell = getViewer().getColumnViewerEditor().getFocusCell();
1146:                                 if (focusCell != null) {
1147:                                         getViewer().update(focusCell.getElement(), null);
1148:                                 }
1149:                         }
1150:
1151:                         @Override
1152:                         public void beforeEditorActivated(ColumnViewerEditorActivationEvent event) {
1153:                                 // do nothing
1154:                         }
1155:
1156:                         @Override
1157:                         public void beforeEditorDeactivated(ColumnViewerEditorDeactivationEvent event) {
1158:                                 // do nothing
1159:                         }
1160:                 }
1161:
1162:                 /**
1163:                  * Maintains references to objects that only live for the length of the edit
1164:                  * cycle.
1165:                  */
1166:                 class EditingState {
1167:                         private final IObservableValue target;
1168:
1169:                         private final IObservableValue model;
1170:
1171:                         private final Binding binding;
1172:
1173:                         EditingState(Binding binding, IObservableValue target, IObservableValue model) {
1174:                                 this.binding = binding;
1175:                                 this.target = target;
1176:                                 this.model = model;
1177:                         }
1178:
1179:                         void dispose() {
1180:                                 binding.dispose();
1181:                                 target.dispose();
1182:                                 model.dispose();
1183:                         }
1184:
1185:                         /**
1186:                          * Checks if an update is really needed.
1187:                          *
1188:                          * @return <code>true</code> if update is really needed, <code>false</code> otherwise.
1189:                          */
1190:                         boolean isUpdateNeeded() {
1191:                                 final Object targetValue = target.getValue();
1192:                                 final Object modelValue = model.getValue();
1193:
1194:                                 if (targetValue == null) {
1195:                                         return modelValue != null;
1196:                                 }
1197:                                 return !targetValue.equals(modelValue);
1198:                         }
1199:                 }
1200:         }
1201:
1202: }