org.eclipse.emf.ecp.view.internal.editor.controls.TableColumnsDMRTableControl.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.emf.ecp.view.internal.editor.controls.TableColumnsDMRTableControl.java

Source

/*******************************************************************************
 * Copyright (c) 2011-2014 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:
 * Eugen - initial API and implementation
 * Johannes Faltermeier - sorting + drag&drop
 *
 ******************************************************************************/
package org.eclipse.emf.ecp.view.internal.editor.controls;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;

import org.eclipse.core.databinding.observable.IObserving;
import org.eclipse.core.databinding.observable.Observables;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.property.value.IValueProperty;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.databinding.EMFDataBindingContext;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecp.core.util.ECPUtil;
import org.eclipse.emf.ecp.internal.ui.Messages;
import org.eclipse.emf.ecp.spi.common.ui.CompositeFactory;
import org.eclipse.emf.ecp.spi.common.ui.composites.SelectionComposite;
import org.eclipse.emf.ecp.view.internal.editor.handler.CreateDomainModelReferenceWizard;
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.SimpleControlSWTRenderer;
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.model.VViewPackage;
import org.eclipse.emf.ecp.view.spi.swt.reporting.RenderingFailedReport;
import org.eclipse.emf.ecp.view.spi.table.model.VTableControl;
import org.eclipse.emf.ecp.view.spi.table.model.VTableDomainModelReference;
import org.eclipse.emf.ecp.view.spi.table.model.VTablePackage;
import org.eclipse.emf.ecp.view.template.model.VTViewTemplateProvider;
import org.eclipse.emf.edit.command.RemoveCommand;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.ui.dnd.EditingDomainViewerDropAdapter;
import org.eclipse.emf.edit.ui.dnd.LocalTransfer;
import org.eclipse.emf.edit.ui.dnd.ViewerDragAdapter;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
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.DatabindingFailedReport;
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.jface.databinding.swt.WidgetProperties;
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.ColumnWeightData;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.TableColumn;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;

/**
 * @author Eugen
 *
 */
@SuppressWarnings("restriction")
public class TableColumnsDMRTableControl extends SimpleControlSWTRenderer {

    private static final EMFFormsDatabinding emfFormsDatabinding;
    private static final EMFFormsLabelProvider emfFormsLabelProvider;
    private static final VTViewTemplateProvider vtViewTemplateProvider;

    static {
        final BundleContext bundleContext = FrameworkUtil.getBundle(TableColumnsDMRTableControl.class)
                .getBundleContext();
        final ServiceReference<EMFFormsDatabinding> emfFormsDatabindingServiceReference = bundleContext
                .getServiceReference(EMFFormsDatabinding.class);
        emfFormsDatabinding = bundleContext.getService(emfFormsDatabindingServiceReference);
        final ServiceReference<EMFFormsLabelProvider> emfFormsLabelProviderServiceReference = bundleContext
                .getServiceReference(EMFFormsLabelProvider.class);
        emfFormsLabelProvider = bundleContext.getService(emfFormsLabelProviderServiceReference);
        final ServiceReference<VTViewTemplateProvider> vtViewTemplateProviderServiceReference = bundleContext
                .getServiceReference(VTViewTemplateProvider.class);
        vtViewTemplateProvider = bundleContext.getService(vtViewTemplateProviderServiceReference);
    }

    private final EMFDataBindingContext viewModelDBC;

    /**
     * Default constructor.
     *
     * @param vElement the view model element to be rendered
     * @param viewContext the view context
     * @param reportService The {@link ReportService}
     */
    public TableColumnsDMRTableControl(VControl vElement, ViewModelContext viewContext,
            ReportService reportService) {
        super(vElement, viewContext, reportService, emfFormsDatabinding, emfFormsLabelProvider,
                vtViewTemplateProvider);
        viewModelDBC = new EMFDataBindingContext();
    }

    private ComposedAdapterFactory composedAdapterFactory;
    private AdapterFactoryLabelProvider labelProvider;
    private AdapterImpl adapter;
    private VTableControl tableControl;
    private EStructuralFeature structuralFeature;
    private EObject eObject;

    /**
     * {@inheritDoc}
     *
     * @see org.eclipse.emf.ecp.view.spi.core.swt.SimpleControlSWTRenderer#createControl(org.eclipse.swt.widgets.Composite)
     */
    @Override
    protected Control createControl(final Composite parent) throws DatabindingFailedException {
        final IObservableValue observableValue = Activator.getDefault().getEMFFormsDatabinding().getObservableValue(
                getVElement().getDomainModelReference(), getViewModelContext().getDomainModel());
        structuralFeature = (EStructuralFeature) observableValue.getValueType();
        eObject = (EObject) ((IObserving) observableValue).getObserved();
        observableValue.dispose();

        final Composite composite = new Composite(parent, SWT.NONE);
        composite.setBackgroundMode(SWT.INHERIT_FORCE);
        GridLayoutFactory.fillDefaults().numColumns(1).applyTo(composite);
        final Composite titleComposite = new Composite(composite, SWT.NONE);
        titleComposite.setBackgroundMode(SWT.INHERIT_FORCE);
        GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).applyTo(titleComposite);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING).grab(true, false).applyTo(titleComposite);

        final Label filler = new Label(titleComposite, SWT.NONE);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, false).applyTo(filler);

        final Composite buttonComposite = new Composite(titleComposite, SWT.NONE);
        buttonComposite.setBackgroundMode(SWT.INHERIT_FORCE);
        GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(true).applyTo(buttonComposite);
        GridDataFactory.fillDefaults().align(SWT.END, SWT.BEGINNING).grab(false, false).applyTo(buttonComposite);

        final Button buttonSort = new Button(buttonComposite, SWT.PUSH);
        buttonSort.setText("Sort"); //$NON-NLS-1$
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(false, false).applyTo(buttonSort);

        final Button buttonAdd = new Button(buttonComposite, SWT.PUSH);
        buttonAdd.setText("Add"); //$NON-NLS-1$
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(false, false).applyTo(buttonAdd);

        final Button buttonRemove = new Button(buttonComposite, SWT.PUSH);
        buttonRemove.setText("Remove"); //$NON-NLS-1$
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(false, false).applyTo(buttonRemove);

        final Composite tableComposite = new Composite(composite, SWT.NONE);
        tableComposite.setBackgroundMode(SWT.INHERIT_FORCE);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).hint(1, 100)
                .applyTo(tableComposite);
        final TableColumnLayout layout = new TableColumnLayout();
        tableComposite.setLayout(layout);

        final TableViewer viewer = new TableViewer(tableComposite);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(viewer.getControl());

        viewer.getTable().setHeaderVisible(true);
        viewer.getTable().setLinesVisible(true);
        final TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
        final TableColumn tableColumn = column.getColumn();
        final EMFFormsLabelProvider emfFormsLabelProvider = Activator.getDefault().getEMFFormsLabelProvider();// TODO
        try {
            final IObservableValue labelText = emfFormsLabelProvider.getDisplayName(
                    getVElement().getDomainModelReference(), getViewModelContext().getDomainModel());
            final IObservableValue tooltip = emfFormsLabelProvider.getDescription(
                    getVElement().getDomainModelReference(), getViewModelContext().getDomainModel());
            viewModelDBC.bindValue(WidgetProperties.text().observe(tableColumn), labelText);
            viewModelDBC.bindValue(WidgetProperties.tooltipText().observe(tableColumn), tooltip);
        } catch (final NoLabelFoundException e) {
            // FIXME Expectations?
            getReportService().report(new RenderingFailedReport(e));
            tableColumn.setText(e.getMessage());
            tableColumn.setToolTipText(e.toString());
        }

        layout.setColumnData(column.getColumn(), new ColumnWeightData(1, true));

        viewer.setLabelProvider(labelProvider);
        viewer.setContentProvider(new ObservableListContentProvider());
        addDragAndDropSupport(viewer, getEditingDomain(eObject));

        final IObservableList list = Activator.getDefault().getEMFFormsDatabinding()
                .getObservableList(getVElement().getDomainModelReference(), getViewModelContext().getDomainModel());
        viewer.setInput(list);

        tableControl = (VTableControl) getViewModelContext().getDomainModel();
        adapter = new TableControlAdapter(parent, viewer);
        tableControl.eAdapters().add(adapter);

        buttonSort.addSelectionListener(new SortSelectionAdapter());

        buttonAdd.addSelectionListener(new AddSelectionAdapter(tableComposite, viewer));

        buttonRemove.addSelectionListener(new RemoveSelectionAdapter(viewer));

        return composite;
    }

    /**
     * @param viewer
     * @param editingDomain
     */
    private void addDragAndDropSupport(TableViewer viewer, EditingDomain editingDomain) {
        final int dndOperations = DND.DROP_MOVE;
        final Transfer[] transfers = new Transfer[] { LocalTransfer.getInstance() };
        viewer.addDragSupport(dndOperations, transfers, new ViewerDragAdapter(viewer));
        final EditingDomainViewerDropAdapter editingDomainViewerDropAdapter = new EditingDomainViewerDropAdapter(
                editingDomain, viewer);
        viewer.addDropSupport(dndOperations, transfers, editingDomainViewerDropAdapter);
    }

    /**
     * {@inheritDoc}
     *
     * @see org.eclipse.emf.ecp.view.spi.core.swt.AbstractControlSWTRenderer#postInit()
     */
    @Override
    protected void postInit() {
        super.postInit();
        composedAdapterFactory = new ComposedAdapterFactory(
                new AdapterFactory[] { new CustomReflectiveItemProviderAdapterFactory(),
                        new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE) });
        labelProvider = new AdapterFactoryLabelProvider(composedAdapterFactory);
    }

    /**
     * {@inheritDoc}
     *
     * @see org.eclipse.emf.ecp.view.spi.core.swt.SimpleControlSWTRenderer#dispose()
     */
    @Override
    protected void dispose() {
        labelProvider.dispose();
        composedAdapterFactory.dispose();
        tableControl.eAdapters().remove(adapter);
        viewModelDBC.dispose();
        super.dispose();
    }

    /**
     * {@inheritDoc}
     *
     * @see org.eclipse.emf.ecp.view.spi.core.swt.SimpleControlSWTRenderer#getUnsetText()
     */
    @Override
    protected String getUnsetText() {
        return "No columns set"; //$NON-NLS-1$
    }

    /**
     * Adapter set on the {@link VTableControl}.
     *
     */
    private final class TableControlAdapter extends AdapterImpl {
        private final Composite parent;
        private final TableViewer viewer;

        /**
         * @param parent
         * @param viewer
         */
        private TableControlAdapter(Composite parent, TableViewer viewer) {
            this.parent = parent;
            this.viewer = viewer;
        }

        /**
         * {@inheritDoc}
         *
         * @see org.eclipse.emf.ecore.util.EContentAdapter#notifyChanged(org.eclipse.emf.common.notify.Notification)
         */
        @Override
        public void notifyChanged(Notification notification) {
            super.notifyChanged(notification);
            if (notification.getFeature() == VTablePackage.eINSTANCE
                    .getTableDomainModelReference_ColumnDomainModelReferences()) {
                viewer.refresh();
                parent.layout();
            }
            if (VTableDomainModelReference.class.isInstance(notification.getNotifier())) {
                updateEObjectAndStructuralFeature();
                viewer.refresh();
                parent.layout();
            }

            if (VTableControl.class.isInstance(notification.getNotifier())
                    && (VTableDomainModelReference.class.isInstance(notification.getNewValue())
                            || VTableDomainModelReference.class.isInstance(notification.getOldValue()))) {
                updateEObjectAndStructuralFeature();
                viewer.refresh();
                parent.layout();
            }
        }

        private void updateEObjectAndStructuralFeature() {
            IObservableValue observableValue;
            IObservableList list;
            try {
                observableValue = Activator.getDefault().getEMFFormsDatabinding().getObservableValue(
                        getVElement().getDomainModelReference(), getViewModelContext().getDomainModel());
                list = Activator.getDefault().getEMFFormsDatabinding().getObservableList(
                        getVElement().getDomainModelReference(), getViewModelContext().getDomainModel());
            } catch (final DatabindingFailedException ex) {
                Activator.getDefault().getReportService().report(new DatabindingFailedReport(ex));
                viewer.setInput(Observables.emptyObservableList());
                return;
            }
            structuralFeature = (EStructuralFeature) observableValue.getValueType();
            eObject = (EObject) ((IObserving) observableValue).getObserved();
            observableValue.dispose();
            viewer.setInput(list);
        }
    }

    /**
     * Reacts on remove button clicks.
     *
     */
    private final class RemoveSelectionAdapter extends SelectionAdapter {
        private final TableViewer viewer;

        /**
         * @param viewer
         */
        private RemoveSelectionAdapter(TableViewer viewer) {
            this.viewer = viewer;
        }

        /**
         * {@inheritDoc}
         *
         * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
         */
        @Override
        public void widgetSelected(SelectionEvent e) {
            super.widgetSelected(e);
            final IStructuredSelection selection = IStructuredSelection.class.cast(viewer.getSelection());

            final EditingDomain editingDomain = getEditingDomain(eObject);
            editingDomain.getCommandStack()
                    .execute(RemoveCommand.create(editingDomain, eObject, structuralFeature, selection.toList()));
        }
    }

    /**
     * Reacts on add button clicks.
     *
     */
    private final class AddSelectionAdapter extends SelectionAdapter {
        private final Composite tableComposite;
        private final TableViewer viewer;

        /**
         * @param tableComposite
         * @param viewer
         */
        private AddSelectionAdapter(Composite tableComposite, TableViewer viewer) {
            this.tableComposite = tableComposite;
            this.viewer = viewer;
        }

        /**
         * {@inheritDoc}
         *
         * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
         */
        @Override
        public void widgetSelected(SelectionEvent e) {
            super.widgetSelected(e);
            final VTableDomainModelReference tableDomainModelReference = VTableDomainModelReference.class
                    .cast(eObject);
            if (tableDomainModelReference == null) {
                Activator.getDefault().getReportService()
                        .report(new AbstractReport("Cannot add column. Table DMR is null.")); //$NON-NLS-1$
                return;
            }

            IValueProperty valueProperty;
            try {
                valueProperty = Activator.getDefault().getEMFFormsDatabinding().getValueProperty(
                        tableDomainModelReference.getDomainModelReference() == null ? tableDomainModelReference
                                : tableDomainModelReference.getDomainModelReference(),
                        getViewModelContext().getDomainModel());
            } catch (final DatabindingFailedException ex) {
                Activator.getDefault().getReportService().report(new DatabindingFailedReport(ex));
                return;
            }
            final EClass eclass = EReference.class.cast(valueProperty.getValueType()).getEReferenceType();

            final Collection<EClass> classes = ECPUtil
                    .getSubClasses(VViewPackage.eINSTANCE.getDomainModelReference());

            final CreateDomainModelReferenceWizard wizard = new CreateDomainModelReferenceWizard(eObject,
                    structuralFeature, getEditingDomain(eObject), eclass, "New Reference Element", //$NON-NLS-1$
                    Messages.NewModelElementWizard_WizardTitle_AddModelElement,
                    Messages.NewModelElementWizard_PageTitle_AddModelElement,
                    Messages.NewModelElementWizard_PageDescription_AddModelElement,
                    (VDomainModelReference) IStructuredSelection.class.cast(viewer.getSelection())
                            .getFirstElement());

            final SelectionComposite<TreeViewer> helper = CompositeFactory
                    .getSelectModelClassComposite(new HashSet<EPackage>(), new HashSet<EPackage>(), classes);
            wizard.setCompositeProvider(helper);

            final WizardDialog wd = new WizardDialog(Display.getDefault().getActiveShell(), wizard);
            wd.open();
            tableComposite.layout();
        }
    }

    /**
     * Reacts on sort button clicks.
     *
     * @author jfaltermeier
     *
     */
    private final class SortSelectionAdapter extends SelectionAdapter {
        private boolean down;

        /**
         * {@inheritDoc}
         *
         * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
         */
        @Override
        public void widgetSelected(SelectionEvent e) {
            super.widgetSelected(e);
            down = !down;
            // EMF API
            @SuppressWarnings("unchecked")
            final List<VDomainModelReference> list = new ArrayList<VDomainModelReference>(
                    (List<VDomainModelReference>) eObject.eGet(structuralFeature, true));
            Collections.sort(list, new Comparator<VDomainModelReference>() {
                @Override
                public int compare(VDomainModelReference o1, VDomainModelReference o2) {
                    final String label1 = labelProvider.getText(o1);
                    final String label2 = labelProvider.getText(o2);
                    int result = label1.compareTo(label2);
                    if (!down) {
                        result *= -1;
                    }
                    return result;
                }
            });
            final EditingDomain editingDomain = getEditingDomain(eObject);
            editingDomain.getCommandStack()
                    .execute(SetCommand.create(editingDomain, eObject, structuralFeature, list));
        }
    }

}