org.eclipse.papyrus.infra.emf.providers.EMFGraphicalContentProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.papyrus.infra.emf.providers.EMFGraphicalContentProvider.java

Source

/*****************************************************************************
 * Copyright (c) 2010 CEA LIST.
 *
 * 
 * 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:
 *  Patrick Tessier (CEA LIST) Patrick.tessier@cea.fr - Initial API and implementation
 *  Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Added graphic contributions for the filters
 *  Remi Schnekenburger (CEA LIST) remi.schnekenburger@cea.fr - Initial History implementation
 *  Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - History integration
 *
 *****************************************************************************/
package org.eclipse.papyrus.infra.emf.providers;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.papyrus.infra.emf.Activator;
import org.eclipse.papyrus.infra.widgets.editors.AbstractEditor;
import org.eclipse.papyrus.infra.widgets.editors.ICommitListener;
import org.eclipse.papyrus.infra.widgets.editors.StringEditor;
import org.eclipse.papyrus.infra.widgets.providers.EncapsulatedContentProvider;
import org.eclipse.papyrus.infra.widgets.providers.IDetailLabelProvider;
import org.eclipse.papyrus.infra.widgets.providers.PatternViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Table;

/**
 * This providers adds a text-filter and an History to EMF-based content providers
 */
//TODO : Extend (Abstract)FilteredContentProvider
public class EMFGraphicalContentProvider extends EncapsulatedContentProvider implements ISelectionChangedListener {

    private static final String DIALOG_SETTINGS = EMFGraphicalContentProvider.class.getName();

    protected String historyId;

    //Unused (yet)
    //TODO : Add a preference or a collapsible composite for this feature (Or both)
    //
    //   /**
    //    * The current metaclass viewer filter
    //    */ 
    //   protected ViewerFilter currentMetaclassViewerFilter;

    protected ViewerFilter patternFilter;

    private static final String HISTORY_SETTINGS = "History"; //$NON-NLS-1$

    private static final String PREVIOUS_SELECTION = "PreviousSelection";

    protected List<EObject> selectionHistory;

    protected CLabel detailLabel;

    protected Object selectedObject;

    protected StructuredViewer viewer;

    protected ResourceSet resourceSet;

    private static final int HISTORY_MAX_SIZE = 5;

    private String currentFilterPattern = ""; //$NON-NLS-1$

    /**
     * the wanted root of the contentprovider
     */

    /**
     * the constructor
     */
    public EMFGraphicalContentProvider(IStructuredContentProvider semanticProvider, ResourceSet resourceSet,
            String historyId) {
        super(semanticProvider);
        this.historyId = historyId;
        this.resourceSet = resourceSet;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void createBefore(Composite parent) {
        createPatternFilter(parent);
    }

    protected void createPatternFilter(Composite parent) {
        StringEditor editor = new StringEditor(parent, SWT.NONE);
        editor.setLabel("Filter:");
        editor.setToolTipText("Enter the name of the element you're looking for. You can use * as a wildcard");
        editor.setValidateOnDelay(true);
        patternFilter = new PatternViewerFilter();
        ((PatternViewerFilter) patternFilter).setPattern(currentFilterPattern);

        editor.addCommitListener(new ICommitListener() {

            public void commit(AbstractEditor editor) {
                String filterPattern = (String) ((StringEditor) editor).getValue();
                ((PatternViewerFilter) patternFilter).setPattern(filterPattern);
                viewer.refresh();
                if (!("".equals(filterPattern) || currentFilterPattern.equals(filterPattern))) {
                    Object firstMatch = getFirstMatchingElement(null);
                    if (firstMatch != null) {
                        revealSemanticElement(Collections.singletonList(firstMatch));
                    }
                    currentFilterPattern = filterPattern;
                }
            }

        });

        List<ViewerFilter> filters = new LinkedList<ViewerFilter>(Arrays.asList(viewer.getFilters()));
        filters.add(patternFilter);
        viewer.setFilters(filters.toArray(new ViewerFilter[filters.size()]));
    }

    /**
     * Returns the first (encapsulated) element matching the current filters
     * 
     * @return
     */
    protected Object getFirstMatchingElement(Object parent) {
        //Browse from the root element
        if (parent == null) {
            for (Object parentElement : getElements(viewer.getInput())) {
                Object firstMatch = getFirstMatchingElement(parentElement);
                if (firstMatch != null) {
                    return firstMatch;
                }
            }
            return null;
        }

        for (ViewerFilter filter : viewer.getFilters()) {
            if (!filter.select(viewer, getParent(parent), parent)) {
                return null;
            }
        }

        //Test the current element
        if (isValidValue(parent)) {
            return parent;
        }

        //Browse the child elements
        for (Object childElement : getChildren(parent)) {
            Object firstMatch = getFirstMatchingElement(childElement);
            if (firstMatch != null) {
                return firstMatch;
            }
        }

        //No match found
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void createAfter(Composite parent) {
        parent.setLayout(new GridLayout(1, false));
        //      createMetaclassFilter(parent); //Disabled
        createHistory(parent);
        createDetailArea(parent);
    }

    /**
     * Creates a widget referencing the recently selected elements
     * 
     * @param parent
     *        The composite in which the widget will be created
     */
    protected void createHistory(Composite parent) {
        initSelectionHistory();

        Group historyGroup = new Group(parent, SWT.NONE);
        historyGroup.setText("Recent selections");
        historyGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
        historyGroup.setLayout(new GridLayout(1, true));

        // table
        Table historyTable = new Table(historyGroup, SWT.BORDER | SWT.SINGLE);
        GridData data = new GridData(SWT.FILL, SWT.FILL, true, false);
        data.heightHint = 70;
        historyTable.setLayoutData(data);
        final TableViewer historyViewer = new TableViewer(historyTable);
        historyViewer.setContentProvider(new HistoryContentProvider());
        historyViewer.setLabelProvider(viewer.getLabelProvider());
        historyViewer.setInput(selectionHistory);
        historyViewer.addSelectionChangedListener(new ISelectionChangedListener() {

            /**
             * {@inheritDoc}
             */
            public void selectionChanged(SelectionChangedEvent event) {
                IStructuredSelection selection = (IStructuredSelection) historyViewer.getSelection();
                Object selectedObject = selection.getFirstElement();
                if (selectedObject instanceof EObject) {
                    EObject eObject = ((EObject) selectedObject);
                    revealSemanticElement(Collections.singletonList(eObject));
                }
            }
        });
    }

    /**
     * Inits the History
     */
    protected void initSelectionHistory() {
        selectionHistory = new ArrayList<EObject>(HISTORY_MAX_SIZE + 1);

        IDialogSettings historySettings = getDialogSettings().getSection(HISTORY_SETTINGS);
        if (historySettings != null && resourceSet != null) {
            String[] uriHistory = historySettings.getArray(PREVIOUS_SELECTION);
            // for each element in the list, try to get the EObject by its URI
            if (uriHistory != null) {
                for (String uri : uriHistory) {
                    try {
                        EObject object = resourceSet.getEObject(URI.createURI(uri), true);
                        if (object != null && !selectionHistory.contains(object)) {
                            selectionHistory.add(object);
                        }
                    } catch (Exception ex) {
                        //Ignore : if the resource doesn't exist anymore, we just skip it
                    }
                }
            }
        }
    }

    /**
     * Creates a widget to filter the tree according to the selected
     * metaclass.
     * 
     * @param parent
     *        The Composite in which the widgets will be created
     * @deprecated
     */
    @Deprecated
    protected void createMetaclassFilter(Composite parent) {
        //      if(semanticRoot == null) {
        //         return;
        //      }
        //
        //      Composite container = new Composite(parent, SWT.NONE);
        //      container.setLayout(new GridLayout(2, false));
        //      container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        //
        //      ResourceSet resourceSet = semanticRoot.eResource().getResourceSet();
        //      EcoreUtil.resolveAll(resourceSet);
        //
        //      Label metamodelLabel = new Label(container, SWT.NONE);
        //      metamodelLabel.setText("Metamodel:");
        //
        //      ComboViewer metamodelViewer = new ComboViewer(container);
        //      metamodelViewer.setContentProvider(getMetamodelContentProvider());
        //      metamodelViewer.setLabelProvider(new EMFLabelProvider());
        //      metamodelViewer.setInput(semanticRoot);
        //      metamodelViewer.getCombo().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        //
        //      Label metaclassLabel = new Label(container, SWT.NONE);
        //      metaclassLabel.setText("Metaclass:");
        //
        //      final ComboViewer metaclassViewer = new ComboViewer(container);
        //      IStructuredContentProvider metaclassProvider = getMetaclassContentProvider();
        //      metaclassViewer.setContentProvider(metaclassProvider);
        //      metaclassViewer.setLabelProvider(new EMFLabelProvider());
        //      metaclassViewer.getCombo().setEnabled(false);
        //      metaclassViewer.getCombo().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        //
        //      metamodelViewer.setFilters(new ViewerFilter[]{ new MetamodelContentFilter(metaclassProvider) });
        //
        //      metamodelViewer.addSelectionChangedListener(new ISelectionChangedListener() {
        //
        //         public void selectionChanged(SelectionChangedEvent event) {
        //            metaclassViewer.setInput(((IStructuredSelection)event.getSelection()).getFirstElement());
        //            metaclassViewer.getCombo().setEnabled(true);
        //         }
        //      });
        //
        //      metaclassViewer.addSelectionChangedListener(new ISelectionChangedListener() {
        //
        //         public void selectionChanged(SelectionChangedEvent event) {
        //            if(!event.getSelection().isEmpty()) {
        //               Object selectedObject = ((IStructuredSelection)event.getSelection()).getFirstElement();
        //               List<ViewerFilter> filters = new LinkedList<ViewerFilter>(Arrays.asList(viewer.getFilters()));
        //               filters.remove(currentMetaclassViewerFilter);
        //               currentMetaclassViewerFilter = getMetaclassViewerFilter(selectedObject);
        //               filters.add(currentMetaclassViewerFilter);
        //               viewer.setFilters(filters.toArray(new ViewerFilter[filters.size()]));
        //               viewer.refresh();
        //            }
        //         }
        //      });
    }

    /**
     * Creates a label widget to display detailed information on the
     * current value (Such as fully qualified name, ...)
     * 
     * @param parent
     *        The composite in which the widget will be created
     */
    protected void createDetailArea(Composite parent) {
        detailLabel = new CLabel(parent, SWT.BORDER);
        detailLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        updateDetailLabel();
    }

    //   @Deprecated
    //   protected IStructuredContentProvider getMetamodelContentProvider() {
    //      return new MetamodelContentProvider();
    //   }
    //
    //   @Deprecated
    //   protected IStructuredContentProvider getMetaclassContentProvider() {
    //      return new MetaclassContentProvider((EClass)this.metaClassWanted, this.metaClassNotWantedList);
    //   }
    //
    //   @Deprecated
    //   protected ILabelProvider getLabelProvider() {
    //      return new EMFObjectLabelProvider();
    //   }
    //
    //   @Deprecated
    //   protected ViewerFilter getMetaclassViewerFilter(Object selectedMetaClass) {
    //      return new MetaclassViewerFilter(selectedMetaClass);
    //   }

    /**
     * Returns the dialog settings. Returned object can't be null.
     * 
     * @return dialog settings for this dialog
     */
    protected IDialogSettings getDialogSettings() {
        IDialogSettings settings = Activator.getDefault().getDialogSettings()
                .getSection(getDialogSettingsIdentifier());
        if (settings == null) {
            settings = Activator.getDefault().getDialogSettings().addNewSection(getDialogSettingsIdentifier());
        }
        return settings;
    }

    private String getDialogSettingsIdentifier() {
        return DIALOG_SETTINGS + "_" + historyId;
    }

    /**
     * Stores dialog settings.
     * 
     * @param settings
     *        settings used to store dialog
     */
    protected void storeDialog(IDialogSettings settings, EObject currentValue) {

        if (selectionHistory.contains(currentValue)) {
            selectionHistory.remove(currentValue);
        }

        selectionHistory.add(0, currentValue);

        //This should loop only once, unless the history was already oversized
        while (selectionHistory.size() > HISTORY_MAX_SIZE) {
            selectionHistory.remove(HISTORY_MAX_SIZE);
        }

        List<String> uriList = new ArrayList<String>();

        // convert list of EObject into URI string list
        for (EObject object : selectionHistory) {
            URI uri = EcoreUtil.getURI(object);
            uriList.add(uri.toString());
        }

        IDialogSettings historySettings = settings.getSection(HISTORY_SETTINGS);
        if (historySettings == null) {
            historySettings = settings.addNewSection(HISTORY_SETTINGS);
        }
        historySettings.put(PREVIOUS_SELECTION, uriList.toArray(new String[uriList.size()]));
    }

    @Override
    public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
        encapsulated.inputChanged(viewer, oldInput, newInput);

        if (viewer instanceof StructuredViewer) {
            this.viewer = (StructuredViewer) viewer;
            if (newInput != null && viewer.getControl() != null && !viewer.getControl().isDisposed()) {
                this.viewer.addSelectionChangedListener(this);
            }
        } else {
            this.viewer = null;
        }
    }

    public void selectionChanged(SelectionChangedEvent event) {
        selectedObject = ((IStructuredSelection) event.getSelection()).getFirstElement();
        updateDetailLabel();
    }

    private void updateDetailLabel() {
        if (detailLabel == null || detailLabel.isDisposed()) {
            return;
        }
        if (selectedObject == null) {
            detailLabel.setText("");
            detailLabel.setImage(null);
        } else {
            ILabelProvider labelProvider = (ILabelProvider) viewer.getLabelProvider();
            String description;
            if (labelProvider instanceof IDetailLabelProvider) {
                description = ((IDetailLabelProvider) labelProvider).getDetail(selectedObject);
            } else {
                description = labelProvider.getText(selectedObject);
            }
            detailLabel.setText(description);
            detailLabel.setImage(labelProvider.getImage(selectedObject));
        }
        detailLabel.getParent().getParent().layout();
    }

    @Override
    public void commit(AbstractEditor editor) {
        Object semanticElement = getAdaptedValue(selectedObject);
        if (semanticElement instanceof EObject) {
            storeDialog(getDialogSettings(), (EObject) semanticElement);
        }
    }

    @Override
    public void dispose() {
        super.dispose();
        viewer.removeSelectionChangedListener(this);
    }
}