| /******************************************************************************* |
| * Copyright (c) 2011-2015 EclipseSource Muenchen GmbH and others. |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * David Soto Setzke - initial API and implementation |
| * Johannes Faltermeier - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.emfforms.spi.view.control.multiattribute; |
| |
| import java.lang.reflect.InvocationTargetException; |
| |
| import javax.inject.Inject; |
| |
| import org.eclipse.core.databinding.Binding; |
| import org.eclipse.core.databinding.observable.IObserving; |
| import org.eclipse.core.databinding.observable.list.IObservableList; |
| import org.eclipse.core.databinding.observable.value.IObservableValue; |
| import org.eclipse.emf.common.notify.AdapterFactory; |
| import org.eclipse.emf.databinding.EMFDataBindingContext; |
| import org.eclipse.emf.ecore.EAttribute; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.InternalEObject; |
| import org.eclipse.emf.ecp.edit.spi.swt.table.ECPCellEditor; |
| import org.eclipse.emf.ecp.view.model.common.edit.provider.CustomReflectiveItemProviderAdapterFactory; |
| import org.eclipse.emf.ecp.view.spi.context.ViewModelContext; |
| import org.eclipse.emf.ecp.view.spi.core.swt.AbstractControlSWTRenderer; |
| import org.eclipse.emf.ecp.view.spi.model.VControl; |
| import org.eclipse.emf.ecp.view.spi.model.VDomainModelReference; |
| import org.eclipse.emf.ecp.view.spi.provider.ECPTooltipModifierHelper; |
| import org.eclipse.emf.ecp.view.spi.renderer.NoPropertyDescriptorFoundExeption; |
| import org.eclipse.emf.ecp.view.spi.renderer.NoRendererFoundException; |
| import org.eclipse.emf.ecp.view.spi.swt.reporting.RenderingFailedReport; |
| import org.eclipse.emf.ecp.view.spi.util.swt.ImageRegistryService; |
| import org.eclipse.emf.ecp.view.template.model.VTViewTemplateProvider; |
| import org.eclipse.emf.edit.command.AddCommand; |
| import org.eclipse.emf.edit.command.MoveCommand; |
| import org.eclipse.emf.edit.command.RemoveCommand; |
| import org.eclipse.emf.edit.domain.EditingDomain; |
| import org.eclipse.emf.edit.provider.ComposedAdapterFactory; |
| import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; |
| import org.eclipse.emfforms.internal.view.control.multiattribute.Messages; |
| import org.eclipse.emfforms.internal.view.control.multiattribute.celleditor.CellEditorFactory; |
| import org.eclipse.emfforms.spi.common.report.AbstractReport; |
| import org.eclipse.emfforms.spi.common.report.ReportService; |
| import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedException; |
| import org.eclipse.emfforms.spi.core.services.databinding.EMFFormsDatabinding; |
| import org.eclipse.emfforms.spi.core.services.label.EMFFormsLabelProvider; |
| import org.eclipse.emfforms.spi.core.services.label.NoLabelFoundException; |
| import org.eclipse.emfforms.spi.swt.core.layout.GridDescriptionFactory; |
| import org.eclipse.emfforms.spi.swt.core.layout.SWTGridCell; |
| import org.eclipse.emfforms.spi.swt.core.layout.SWTGridDescription; |
| import org.eclipse.jface.databinding.viewers.ObservableListContentProvider; |
| import org.eclipse.jface.layout.GridDataFactory; |
| import org.eclipse.jface.layout.GridLayoutFactory; |
| import org.eclipse.jface.layout.TableColumnLayout; |
| import org.eclipse.jface.viewers.CellEditor; |
| import org.eclipse.jface.viewers.ColumnViewer; |
| import org.eclipse.jface.viewers.ColumnViewerEditor; |
| import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent; |
| import org.eclipse.jface.viewers.ColumnViewerEditorActivationListener; |
| import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy; |
| import org.eclipse.jface.viewers.ColumnViewerEditorDeactivationEvent; |
| import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; |
| import org.eclipse.jface.viewers.ColumnWeightData; |
| import org.eclipse.jface.viewers.EditingSupport; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.jface.viewers.TableViewer; |
| import org.eclipse.jface.viewers.TableViewerColumn; |
| import org.eclipse.jface.viewers.TableViewerEditor; |
| import org.eclipse.jface.viewers.TableViewerRow; |
| import org.eclipse.jface.viewers.ViewerCell; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Table; |
| import org.eclipse.swt.widgets.TableItem; |
| import org.osgi.framework.FrameworkUtil; |
| |
| /** |
| * Renderer for MultiReferenceControl. |
| * |
| * @author David Soto Setzke |
| * @author Johannes Faltermeier |
| * |
| */ |
| public class MultiAttributeSWTRenderer extends AbstractControlSWTRenderer<VControl> { |
| |
| private static final String ICON_ADD = "icons/add.png"; //$NON-NLS-1$ |
| private static final String ICON_DELETE = "icons/delete.png"; //$NON-NLS-1$ |
| private static final String ICONS_ARROW_DOWN_PNG = "icons/arrow_down.png";//$NON-NLS-1$ |
| private static final String ICONS_ARROW_UP_PNG = "icons/arrow_up.png";//$NON-NLS-1$ |
| |
| private final ImageRegistryService imageRegistryService; |
| |
| private AdapterFactoryLabelProvider labelProvider; |
| private ComposedAdapterFactory composedAdapterFactory; |
| |
| private Composite mainComposite; |
| private TableViewer tableViewer; |
| private Button removeButton; |
| private Button addButton; |
| |
| private final EMFDataBindingContext viewModelDBC; |
| private Label validationIcon; |
| |
| /** |
| * Default constructor. |
| * |
| * @param vElement |
| * the view model element to be rendered |
| * @param viewContext |
| * the view context |
| * @param emfFormsDatabinding |
| * The {@link EMFFormsDatabinding} |
| * @param emfFormsLabelProvider |
| * The {@link EMFFormsLabelProvider} |
| * @param reportService |
| * The {@link ReportService} |
| * @param vtViewTemplateProvider |
| * The {@link VTViewTemplateProvider} |
| * @param imageRegistryService |
| * The {@link ImageRegistryService} |
| */ |
| @Inject |
| public MultiAttributeSWTRenderer(VControl vElement, ViewModelContext viewContext, ReportService reportService, |
| EMFFormsDatabinding emfFormsDatabinding, EMFFormsLabelProvider emfFormsLabelProvider, |
| VTViewTemplateProvider vtViewTemplateProvider, ImageRegistryService imageRegistryService) { |
| super(vElement, viewContext, reportService, emfFormsDatabinding, emfFormsLabelProvider, vtViewTemplateProvider); |
| this.imageRegistryService = imageRegistryService; |
| viewModelDBC = new EMFDataBindingContext(); |
| } |
| |
| @Override |
| public SWTGridDescription getGridDescription(SWTGridDescription gridDescription) { |
| return GridDescriptionFactory.INSTANCE.createSimpleGrid(1, 1, this); |
| } |
| |
| /** |
| * Returns the height for the table that will be created. |
| * |
| * @return the height hint |
| */ |
| protected int getTableHeightHint() { |
| return 200; |
| } |
| |
| /** |
| * Gives access to the tableViewer used to display the attributes. |
| * |
| * @return the viewer |
| */ |
| protected TableViewer getTableViewer() { |
| return tableViewer; |
| } |
| |
| /** |
| * Creates the composite which will be the parent for the table. |
| * |
| * @param composite |
| * the parent composite |
| * @return the table composite |
| */ |
| protected Composite createControlComposite(Composite composite) { |
| final Composite controlComposite = new Composite(composite, SWT.NONE); |
| GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).hint(1, getTableHeightHint()) |
| .applyTo(controlComposite); |
| GridLayoutFactory.fillDefaults().numColumns(1).applyTo(controlComposite); |
| return controlComposite; |
| } |
| |
| /** |
| * Returns an {@link Image} from the image registry. |
| * |
| * @param path |
| * the path to the image |
| * @return the image |
| */ |
| protected Image getImage(String path) { |
| return imageRegistryService.getImage(FrameworkUtil.getBundle(getClass()), path); |
| } |
| |
| private Button createRemoveRowButton(final Composite buttonComposite, IObservableList list, EAttribute attribute) { |
| removeButton = new Button(buttonComposite, SWT.None); |
| final Image image = getImage(ICON_DELETE); |
| removeButton.setImage(image); |
| removeButton.setEnabled(!getVElement().isReadonly()); |
| if (list.size() <= attribute.getLowerBound()) { |
| removeButton.setEnabled(false); |
| } |
| return removeButton; |
| } |
| |
| private Button createAddRowButton(final Composite buttonComposite, IObservableList list, EAttribute attribute) { |
| addButton = new Button(buttonComposite, SWT.None); |
| final Image image = getImage(ICON_ADD); |
| addButton.setImage(image); |
| if (attribute.getUpperBound() != -1 && list.size() >= attribute.getUpperBound()) { |
| addButton.setEnabled(false); |
| } |
| return addButton; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.emf.ecp.view.spi.swt.AbstractSWTRenderer#renderControl(org.eclipse.emf.ecp.view.spi.swt.layout.SWTGridCell, |
| * org.eclipse.swt.widgets.Composite) |
| */ |
| @Override |
| protected Control renderControl(SWTGridCell cell, Composite parent) |
| throws NoRendererFoundException, NoPropertyDescriptorFoundExeption { |
| |
| final Composite composite = new Composite(parent, SWT.NONE); |
| composite.setLayout(new GridLayout(1, false)); |
| composite.setBackground(parent.getBackground()); |
| |
| IObservableList list; |
| try { |
| list = getEMFFormsDatabinding().getObservableList(getVElement().getDomainModelReference(), |
| getViewModelContext().getDomainModel()); |
| } catch (final DatabindingFailedException ex1) { |
| getReportService().report(new RenderingFailedReport(ex1)); |
| return composite; |
| } |
| |
| final EAttribute attribute = EAttribute.class.cast(list.getElementType()); |
| |
| final Composite titleComposite = new Composite(composite, SWT.NONE); |
| titleComposite.setBackground(parent.getBackground()); |
| GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.BEGINNING).applyTo(titleComposite); |
| GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(false).applyTo(titleComposite); |
| createLabelProvider(); |
| |
| validationIcon = createValidationIcon(titleComposite); |
| GridDataFactory.fillDefaults().hint(16, 17).grab(false, false).applyTo(validationIcon); |
| |
| Button addButton = null; |
| Button removeButton = null; |
| final Composite buttonComposite = new Composite(titleComposite, SWT.NONE); |
| buttonComposite.setBackground(titleComposite.getBackground()); |
| GridDataFactory.fillDefaults().align(SWT.END, SWT.BEGINNING).grab(true, false).applyTo(buttonComposite); |
| int numButtons = 0; |
| if (attribute.isOrdered()) { |
| createUpDownButtons(buttonComposite, list); |
| numButtons += 2; |
| } |
| |
| addButton = createAddRowButton(buttonComposite, list, attribute); |
| removeButton = createRemoveRowButton(buttonComposite, list, attribute); |
| numButtons += 2; |
| |
| GridLayoutFactory.fillDefaults().numColumns(numButtons).equalWidth(false).applyTo(buttonComposite); |
| final Composite controlComposite = createControlComposite(composite); |
| createContent(controlComposite, attribute, list); |
| |
| initAddButton(addButton, list); |
| initRemoveButton(removeButton, list); |
| |
| getTableViewer().addSelectionChangedListener(new ISelectionChangedListener() { |
| @Override |
| public void selectionChanged(SelectionChangedEvent event) { |
| MultiAttributeSWTRenderer.this.removeButton.setEnabled(!event.getSelection().isEmpty()); |
| } |
| }); |
| |
| return composite; |
| } |
| |
| private void createLabelProvider() { |
| composedAdapterFactory = new ComposedAdapterFactory( |
| new AdapterFactory[] { new CustomReflectiveItemProviderAdapterFactory(), |
| new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE) }); |
| labelProvider = new AdapterFactoryLabelProvider(composedAdapterFactory); |
| labelProvider.setFireLabelUpdateNotifications(true); |
| } |
| |
| private void initAddButton(Button addButton, IObservableList list) { |
| if (addButton == null) { |
| return; |
| } |
| addButton.addSelectionListener(new AddButtonSelectionAdapter(list)); |
| } |
| |
| private void initRemoveButton(Button removeButton, IObservableList list) { |
| if (removeButton == null) { |
| return; |
| } |
| removeButton.addSelectionListener(new RemoveButtonSelectionAdapter(list)); |
| } |
| |
| private void createUpDownButtons(Composite composite, IObservableList list) { |
| final Image up = getImage(ICONS_ARROW_UP_PNG); |
| final Image down = getImage(ICONS_ARROW_DOWN_PNG); |
| |
| final Button upB = new Button(composite, SWT.PUSH); |
| upB.setImage(up); |
| upB.setEnabled(!getVElement().isReadonly()); |
| upB.addSelectionListener(new UpButtonSelectionAdapter(list)); |
| final Button downB = new Button(composite, SWT.PUSH); |
| downB.setImage(down); |
| downB.setEnabled(!getVElement().isReadonly()); |
| downB.addSelectionListener(new DownButtonSelectionAdapter(list)); |
| } |
| |
| private InternalEObject getInstanceOf(EClass clazz) { |
| return InternalEObject.class.cast(clazz.getEPackage().getEFactoryInstance().create(clazz)); |
| } |
| |
| private void createContent(Composite composite, EAttribute attribute, IObservableList list) { |
| tableViewer = new TableViewer(composite, SWT.MULTI | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER); |
| tableViewer.getTable().setData(CUSTOM_VARIANT, "org_eclipse_emf_ecp_control_multiattribute"); //$NON-NLS-1$ |
| tableViewer.getTable().setHeaderVisible(true); |
| tableViewer.getTable().setLinesVisible(true); |
| |
| final ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(tableViewer) { |
| @Override |
| protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) { |
| return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL |
| || event.eventType == ColumnViewerEditorActivationEvent.MOUSE_CLICK_SELECTION |
| || event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.CR |
| || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC; |
| } |
| }; |
| |
| TableViewerEditor.create(tableViewer, null, actSupport, |
| ColumnViewerEditor.TABBING_HORIZONTAL | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR |
| | ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION); |
| ColumnViewerToolTipSupport.enableFor(tableViewer); |
| |
| final ObservableListContentProvider cp = new ObservableListContentProvider(); |
| |
| final EMFFormsLabelProvider labelService = getEMFFormsLabelProvider(); |
| |
| final TableViewerColumn column = new TableViewerColumn(tableViewer, SWT.NONE); |
| column.getColumn().setResizable(false); |
| column.getColumn().setMoveable(false); |
| |
| final EClass clazz = attribute.getEContainingClass(); |
| InternalEObject tempInstance = null; |
| if (!clazz.isAbstract() && !clazz.isInterface()) { |
| tempInstance = getInstanceOf(clazz); |
| } |
| |
| final CellEditor cellEditor = createCellEditor(tempInstance, attribute, tableViewer.getTable()); |
| |
| @SuppressWarnings("deprecation") |
| final IObservableValue textObservableValue = org.eclipse.jface.databinding.swt.SWTObservables |
| .observeText(column.getColumn()); |
| @SuppressWarnings("deprecation") |
| final IObservableValue tooltipObservableValue = org.eclipse.jface.databinding.swt.SWTObservables |
| .observeTooltipText(column.getColumn()); |
| try { |
| viewModelDBC.bindValue(textObservableValue, labelService |
| .getDisplayName(getVElement().getDomainModelReference(), getViewModelContext().getDomainModel())); |
| |
| viewModelDBC.bindValue(tooltipObservableValue, labelService |
| .getDescription(getVElement().getDomainModelReference(), getViewModelContext().getDomainModel())); |
| } catch (final NoLabelFoundException e) { |
| getReportService().report(new RenderingFailedReport(e)); |
| } |
| |
| tableViewer.setLabelProvider(labelProvider); |
| tableViewer.setContentProvider(cp); |
| tableViewer.setInput(list); |
| |
| final TableColumnLayout layout = new TableColumnLayout(); |
| composite.setLayout(layout); |
| layout.setColumnData(column.getColumn(), new ColumnWeightData(1, false)); |
| |
| final VDomainModelReference dmr = getVElement().getDomainModelReference(); |
| final EditingSupport observableSupport = new ECPListEditingSupport(tableViewer, cellEditor, getVElement(), dmr, |
| list); |
| column.setEditingSupport(observableSupport); |
| |
| } |
| |
| private CellEditor createCellEditor(final EObject tempInstance, final EAttribute attribute, Table table) { |
| return CellEditorFactory.INSTANCE.createCellEditor(attribute, tempInstance, table, getViewModelContext()); |
| } |
| |
| @Override |
| protected void applyValidation() { |
| Display.getDefault().asyncExec(new Runnable() { |
| |
| @Override |
| public void run() { |
| if (validationIcon == null) { |
| return; |
| } |
| if (validationIcon.isDisposed()) { |
| return; |
| } |
| if (getVElement().getDiagnostic() == null) { |
| return; |
| } |
| validationIcon.setImage(getValidationIcon(getVElement().getDiagnostic().getHighestSeverity())); |
| validationIcon.setToolTipText(ECPTooltipModifierHelper.modifyString(getVElement().getDiagnostic() |
| .getMessage(), null)); |
| } |
| }); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void dispose() { |
| if (mainComposite != null) { |
| mainComposite.dispose(); |
| } |
| if (labelProvider != null) { |
| labelProvider.dispose(); |
| } |
| if (composedAdapterFactory != null) { |
| composedAdapterFactory.dispose(); |
| } |
| super.dispose(); |
| } |
| |
| /** |
| * Listener for the down button. |
| * |
| * @author David Soto Setzke |
| * @author Johannes Faltermeier |
| * |
| */ |
| private final class DownButtonSelectionAdapter extends SelectionAdapter { |
| |
| private final IObservableList list; |
| |
| DownButtonSelectionAdapter(IObservableList list) { |
| this.list = list; |
| } |
| |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| final IObserving observing = IObserving.class.cast(list); |
| final EObject eObject = EObject.class.cast(observing.getObserved()); |
| final EAttribute attribute = EAttribute.class.cast(list.getElementType()); |
| |
| final int currentIndex = tableViewer.getTable().getSelectionIndex(); |
| if (currentIndex + 1 < tableViewer.getTable().getItems().length) { |
| final EditingDomain editingDomain = getEditingDomain(eObject); |
| editingDomain.getCommandStack() |
| .execute(new MoveCommand(editingDomain, eObject, attribute, currentIndex, currentIndex + 1)); |
| tableViewer.refresh(); |
| } |
| } |
| } |
| |
| /** |
| * Listener for the up button. |
| * |
| * @author David Soto Setzke |
| * @author Johannes Faltermeier |
| * |
| */ |
| private final class UpButtonSelectionAdapter extends SelectionAdapter { |
| |
| private final IObservableList list; |
| |
| UpButtonSelectionAdapter(IObservableList list) { |
| this.list = list; |
| } |
| |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| final IObserving observing = IObserving.class.cast(list); |
| final EObject eObject = EObject.class.cast(observing.getObserved()); |
| final EAttribute attribute = EAttribute.class.cast(list.getElementType()); |
| |
| final int currentIndex = tableViewer.getTable().getSelectionIndex(); |
| if (currentIndex != 0) { |
| final EditingDomain editingDomain = getEditingDomain(eObject); |
| |
| editingDomain.getCommandStack() |
| .execute(new MoveCommand(editingDomain, eObject, attribute, currentIndex, currentIndex - 1)); |
| tableViewer.refresh(); |
| } |
| } |
| } |
| |
| /** |
| * Listener for the remove button. |
| * |
| * @author David Soto Setzke |
| * @author Johannes Faltermeier |
| * |
| */ |
| private final class RemoveButtonSelectionAdapter extends SelectionAdapter { |
| |
| private final IObservableList list; |
| |
| RemoveButtonSelectionAdapter(IObservableList list) { |
| this.list = list; |
| } |
| |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| final IObserving observing = IObserving.class.cast(list); |
| final EObject eObject = EObject.class.cast(observing.getObserved()); |
| final EAttribute attribute = EAttribute.class.cast(list.getElementType()); |
| |
| final EditingDomain editingDomain = getEditingDomain(eObject); |
| final int currentIndex = tableViewer.getTable().getSelectionIndex(); |
| if (currentIndex >= 0) { |
| editingDomain.getCommandStack().execute(RemoveCommand.create(editingDomain, eObject, attribute, |
| tableViewer.getElementAt(currentIndex))); |
| } |
| } |
| } |
| |
| /** |
| * Listener for the add button. |
| * |
| * @author David Soto Setzke |
| * @author Johannes Faltermeier |
| * |
| */ |
| private final class AddButtonSelectionAdapter extends SelectionAdapter { |
| |
| private final IObservableList list; |
| |
| AddButtonSelectionAdapter(IObservableList list) { |
| this.list = list; |
| } |
| |
| @Override |
| public void widgetSelected(SelectionEvent event) { |
| try { |
| final IObserving observing = IObserving.class.cast(list); |
| final EObject eObject = EObject.class.cast(observing.getObserved()); |
| final EAttribute attribute = EAttribute.class.cast(list.getElementType()); |
| |
| Object defaultValue = attribute.getEType().getDefaultValue(); |
| if (defaultValue == null) { |
| defaultValue = attribute.getEType().getInstanceClass().getConstructor().newInstance(); |
| |
| } |
| final EditingDomain editingDomain = getEditingDomain(getViewModelContext().getDomainModel()); |
| editingDomain.getCommandStack() |
| .execute(AddCommand.create(editingDomain, eObject, attribute, defaultValue)); |
| tableViewer.refresh(); |
| } catch (final InstantiationException ex) { |
| getReportService().report(new AbstractReport(ex, Messages.MultiAttributeSWTRenderer_AddFailed)); |
| } catch (final IllegalAccessException ex) { |
| getReportService().report(new AbstractReport(ex, Messages.MultiAttributeSWTRenderer_AddFailed)); |
| } catch (final IllegalArgumentException ex) { |
| getReportService().report(new AbstractReport(ex, Messages.MultiAttributeSWTRenderer_AddFailed)); |
| } catch (final InvocationTargetException ex) { |
| getReportService().report(new AbstractReport(ex, Messages.MultiAttributeSWTRenderer_AddFailed)); |
| } catch (final NoSuchMethodException ex) { |
| getReportService().report(new AbstractReport(ex, Messages.MultiAttributeSWTRenderer_AddFailed)); |
| } catch (final SecurityException ex) { |
| getReportService().report(new AbstractReport(ex, Messages.MultiAttributeSWTRenderer_AddFailed)); |
| } |
| } |
| } |
| |
| /** |
| * Editing support for a single element in a multi {@link EAttribute}. |
| * |
| * @author jfaltermeier |
| * |
| */ |
| private class ECPListEditingSupport extends EditingSupport { |
| |
| private final CellEditor cellEditor; |
| |
| private final VControl control; |
| |
| private final IObservableList valueProperty; |
| |
| ECPListEditingSupport(ColumnViewer viewer, CellEditor cellEditor, VControl control, |
| VDomainModelReference domainModelReference, IObservableList valueProperty) { |
| super(viewer); |
| this.cellEditor = cellEditor; |
| this.control = control; |
| this.valueProperty = valueProperty; |
| } |
| |
| private EditingState editingState; |
| |
| private final ColumnViewerEditorActivationListenerHelper activationListener = new ColumnViewerEditorActivationListenerHelper(); |
| |
| /** |
| * Default implementation always returns <code>true</code>. |
| * |
| * @see org.eclipse.jface.viewers.EditingSupport#canEdit(java.lang.Object) |
| */ |
| @Override |
| protected boolean canEdit(Object element) { |
| |
| final boolean editable = control.isEnabled() && !control.isReadonly(); |
| |
| if (ECPCellEditor.class.isInstance(cellEditor)) { |
| ECPCellEditor.class.cast(cellEditor).setEditable(editable); |
| return true; |
| } |
| return editable; |
| } |
| |
| /** |
| * Default implementation always returns <code>null</code> as this will |
| * be handled by the Binding. |
| * |
| * @see org.eclipse.jface.viewers.EditingSupport#getValue(java.lang.Object) |
| */ |
| @Override |
| protected Object getValue(Object element) { |
| // no op |
| return null; |
| } |
| |
| /** |
| * Default implementation does nothing as this will be handled by the |
| * Binding. |
| * |
| * @see org.eclipse.jface.viewers.EditingSupport#setValue(java.lang.Object, |
| * java.lang.Object) |
| */ |
| @Override |
| protected void setValue(Object element, Object value) { |
| // no op |
| } |
| |
| /** |
| * Creates a {@link Binding} between the editor and the element to be |
| * edited. Invokes {@link #doCreateCellEditorObservable(CellEditor)}, |
| * {@link #doCreateElementObservable(Object, ViewerCell)}, and then |
| * {@link #createBinding(IObservableValue, IObservableValue)}. |
| */ |
| @Override |
| protected void initializeCellEditorValue(CellEditor cellEditor, ViewerCell cell) { |
| |
| final IObservableValue target = doCreateCellEditorObservable(cellEditor); |
| final TableViewerRow viewerRow = (TableViewerRow) cell.getViewerRow(); |
| final TableItem item = (TableItem) viewerRow.getItem(); |
| final int index = item.getParent().indexOf(item); |
| @SuppressWarnings("restriction") |
| final IObservableValue model = new org.eclipse.emf.ecp.edit.internal.swt.util.ECPObservableValue( |
| valueProperty, index, String.class); |
| |
| final Binding binding = createBinding(target, model); |
| |
| editingState = new EditingState(binding, target, model); |
| |
| getViewer().getColumnViewerEditor().addEditorActivationListener(activationListener); |
| } |
| |
| @Override |
| protected CellEditor getCellEditor(Object element) { |
| return cellEditor; |
| } |
| |
| protected Binding createBinding(IObservableValue target, IObservableValue model) { |
| if (ECPCellEditor.class.isInstance(cellEditor)) { |
| return getDataBindingContext().bindValue(target, model, |
| ((ECPCellEditor) cellEditor).getTargetToModelStrategy(getDataBindingContext()), |
| ((ECPCellEditor) cellEditor).getModelToTargetStrategy(getDataBindingContext())); |
| } |
| return getDataBindingContext().bindValue(target, model); |
| } |
| |
| @SuppressWarnings("deprecation") |
| protected IObservableValue doCreateCellEditorObservable(CellEditor cellEditor) { |
| if (ECPCellEditor.class.isInstance(cellEditor)) { |
| return ((ECPCellEditor) cellEditor).getValueProperty().observe(cellEditor); |
| } |
| return org.eclipse.jface.databinding.swt.SWTObservables.observeText(cellEditor.getControl(), SWT.FocusOut); |
| } |
| |
| @Override |
| protected final void saveCellEditorValue(CellEditor cellEditor, ViewerCell cell) { |
| editingState.binding.updateTargetToModel(); |
| } |
| |
| /** |
| * A ColumnViewerEditorActivationListener to reset the cells after focus |
| * lost. |
| * |
| * @author Eugen Neufeld |
| * |
| */ |
| private class ColumnViewerEditorActivationListenerHelper extends ColumnViewerEditorActivationListener { |
| |
| @Override |
| public void afterEditorActivated(ColumnViewerEditorActivationEvent event) { |
| // do nothing |
| } |
| |
| @Override |
| public void afterEditorDeactivated(ColumnViewerEditorDeactivationEvent event) { |
| editingState.dispose(); |
| editingState = null; |
| |
| getViewer().getColumnViewerEditor().removeEditorActivationListener(this); |
| final ViewerCell focusCell = getViewer().getColumnViewerEditor().getFocusCell(); |
| if (focusCell != null) { |
| getViewer().update(focusCell.getElement(), null); |
| } |
| } |
| |
| @Override |
| public void beforeEditorActivated(ColumnViewerEditorActivationEvent event) { |
| // do nothing |
| } |
| |
| @Override |
| public void beforeEditorDeactivated(ColumnViewerEditorDeactivationEvent event) { |
| // do nothing |
| } |
| } |
| |
| /** |
| * Maintains references to objects that only live for the length of the |
| * edit cycle. |
| */ |
| class EditingState { |
| private final IObservableValue target; |
| |
| private final IObservableValue model; |
| |
| private final Binding binding; |
| |
| EditingState(Binding binding, IObservableValue target, IObservableValue model) { |
| this.binding = binding; |
| this.target = target; |
| this.model = model; |
| } |
| |
| void dispose() { |
| binding.dispose(); |
| target.dispose(); |
| model.dispose(); |
| } |
| } |
| } |
| |
| } |