org.eclipse.sirius.diagram.ui.tools.api.wizards.page.DiagramSelectionWizardPage.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.sirius.diagram.ui.tools.api.wizards.page.DiagramSelectionWizardPage.java

Source

/*******************************************************************************
 * Copyright (c) 2008 THALES GLOBAL SERVICES.
 * 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:
 *    Obeo - initial API and implementation
 *******************************************************************************/
package org.eclipse.sirius.diagram.ui.tools.api.wizards.page;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;

import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.sirius.business.api.query.IdentifiedElementQuery;
import org.eclipse.sirius.common.tools.api.util.StringUtil;
import org.eclipse.sirius.diagram.DDiagram;
import org.eclipse.sirius.diagram.DSemanticDiagram;
import org.eclipse.sirius.viewpoint.DRepresentation;
import org.eclipse.sirius.viewpoint.DRepresentationContainer;
import org.eclipse.sirius.viewpoint.DSemanticDecorator;
import org.eclipse.sirius.viewpoint.DView;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer;
import org.eclipse.ui.navigator.ICommonContentExtensionSite;
import org.eclipse.ui.navigator.ICommonContentProvider;

/**
 * Wizard to select diagrams from an Aird.
 * 
 * @author ymortier
 */
public class DiagramSelectionWizardPage extends WizardPage {

    private static final String SELECT_DIAGRAMS_TO_EXPORT = "Select Diagrams to export";

    /** The title of the page. */
    private static final String PAGE_TITLE = "Select diagrams to export";

    /** The page is completed. */
    private static final int CODE_OK = 0;

    /** The user has not selected one or more diagrams. */
    private static final int CODE_NO_SEL = 1;

    /** The user has selected an object that is not a diagram. */
    private static final int CODE_ERROR = 2;

    /** The composite control of the page. */
    private Composite pageComposite;

    /** The table viewer. */
    private CheckboxTreeViewer treeViewer;

    /** The root element. */
    private DView root;

    /** The filter. */
    private ViewerFilter diagramSelectionFilter;

    /**
     * Create a new <code>DescDiagramSelectionWizardPage</code>.
     * 
     * @param root
     *            the root object
     */
    public DiagramSelectionWizardPage(final DView root) {
        super(PAGE_TITLE);
        initialize(root, new DiagramSelectionFilter());
    }

    /**
     * Create a new <code>DescDiagramSelectionWizardPage</code>.
     * 
     * @param root
     *            the root object
     * @param diagramSelectionFilter
     *            specific diagramSelectionFilter (the default
     *            diagramSelectionFilter display all the DDiagram instances).
     * @since 0.9.0
     */
    public DiagramSelectionWizardPage(final DView root, final ViewerFilter diagramSelectionFilter) {
        super(PAGE_TITLE);
        initialize(root, diagramSelectionFilter);
    }

    private void initialize(final DView aRoot, final ViewerFilter aDiagramSelectionFilter) {
        this.root = aRoot;
        this.setPageComplete(false);
        this.diagramSelectionFilter = aDiagramSelectionFilter;

        setMessage(SELECT_DIAGRAMS_TO_EXPORT, IMessageProvider.INFORMATION);

        final StringBuilder title = new StringBuilder();
        title.append(PAGE_TITLE);
        if (root.getViewpoint() != null
                && !StringUtil.isEmpty(new IdentifiedElementQuery(root.getViewpoint()).getLabel())) {
            title.append(" for ");
            title.append(new IdentifiedElementQuery(root.getViewpoint()).getLabel());
        }
        this.setTitle(title.toString());
    }

    /**
     * {@inheritDoc}
     * 
     * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
     */
    public void createControl(final Composite parent) {
        initializeDialogUnits(parent);

        pageComposite = new Composite(parent, SWT.NONE);
        pageComposite.setLayout(new GridLayout());
        pageComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));

        this.treeViewer = createTreeViewer(pageComposite);
        treeViewer.setInput(((DRepresentationContainer) root).getModels().iterator().next());
        treeViewer.addFilter(this.diagramSelectionFilter);
        treeViewer.expandAll();
        treeViewer.collapseAll();
        setControl(pageComposite);
    }

    /**
     * Create the table viewer.
     * 
     * @param parent
     *            the parent composite.
     * @return the table viewer.
     */
    private CheckboxTreeViewer createTreeViewer(final Composite parent) {
        final ContainerCheckedTreeViewer viewer = new DescDiagramSelectionTreeViewer(parent,
                SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);

        final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
        viewer.getControl().setLayoutData(gridData);
        viewer.getTree().setHeaderVisible(false);
        viewer.getTree().setLinesVisible(false);
        viewer.addCheckStateListener(new SiriusDiagramSelectionCheckStateListener());

        // TODOYMO check the type of root ! Change the type in constructor !
        viewer.setContentProvider(new SemanticDViewContentProvider(this.root));
        final ComposedAdapterFactory composedAdapterFactory = new ComposedAdapterFactory(
                ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
        viewer.setLabelProvider(new AdapterFactoryLabelProvider(composedAdapterFactory));

        return viewer;
    }

    /**
     * Filter the tree.
     * 
     * @author ymortier
     */
    private class DiagramSelectionFilter extends ViewerFilter {

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer,
         *      java.lang.Object, java.lang.Object)
         */
        @Override
        public boolean select(final Viewer viewer, final Object parentElement, final Object element) {
            if (element instanceof EObject && treeViewer.getContentProvider() != null) {
                final EObject eObject = (EObject) element;
                boolean resultForThis = baseSelect(eObject);
                final Object[] children = ((ITreeContentProvider) treeViewer.getContentProvider())
                        .getChildren(element);
                if (children != null) {
                    for (int i = 0; i < children.length && !resultForThis; i++) {
                        resultForThis = select(viewer, element, children[i]);
                    }
                }
                return resultForThis;
            }
            return false;
        }

        private boolean baseSelect(final Object element) {
            return element instanceof DDiagram;
        }
    }

    /**
     * Change the page according to the new state of the selection.
     * 
     * @author ymortier
     */
    private class SiriusDiagramSelectionCheckStateListener implements ICheckStateListener {

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.jface.viewers.ICheckStateListener#checkStateChanged(org.eclipse.jface.viewers.CheckStateChangedEvent)
         */
        public void checkStateChanged(final CheckStateChangedEvent event) {
            final int result = checkSelection(getSelectedElements());
            switch (result) {
            case CODE_OK:
                setMessage(SELECT_DIAGRAMS_TO_EXPORT, IMessageProvider.INFORMATION);
                setPageComplete(true);
                break;
            case CODE_NO_SEL:
                setMessage(SELECT_DIAGRAMS_TO_EXPORT, IMessageProvider.INFORMATION);
                setPageComplete(false);
                break;
            case CODE_ERROR:
                setMessage("You must select Diagrams", IMessageProvider.ERROR);
                setPageComplete(false);
                break;
            default:
                setMessage("Unknown code result", IMessageProvider.ERROR);
                setPageComplete(false);
                break;
            }
        }

    }

    private int checkSelection(final Collection<?> selectedItems) {
        int result = CODE_OK;
        if (selectedItems.isEmpty()) {
            result = CODE_NO_SEL;
        } else {
            final Iterator<?> iterItems = selectedItems.iterator();
            while (iterItems.hasNext()) {
                final Object next = iterItems.next();
                if (!(next instanceof DDiagram)) {
                    result = CODE_ERROR;
                }
            }
        }
        return result;
    }

    /**
     * Selects only diagrams.
     * 
     * @author ymortier
     */
    public static class DescDiagramSelectionTreeViewer extends ContainerCheckedTreeViewer {

        /**
         * Create a new <code>DescDiagramSelectionTreeViewer</code>.
         * 
         * @param parent
         *            the parent composite.
         */
        public DescDiagramSelectionTreeViewer(final Composite parent) {
            super(parent);
        }

        /**
         * Create a new <code>DescDiagramSelectionTreeViewer</code>.
         * 
         * @param parent
         *            the parent composite.
         * @param style
         *            the style.
         */
        public DescDiagramSelectionTreeViewer(final Composite parent, final int style) {
            super(parent, style);
        }

        /**
         * Create a new <code>DescDiagramSelectionTreeViewer</code>.
         * 
         * @param tree
         *            the tree.
         */
        public DescDiagramSelectionTreeViewer(final Tree tree) {
            super(tree);
        }

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.ui.dialogs.ContainerCheckedTreeViewer#doCheckStateChanged(java.lang.Object)
         */
        @Override
        protected void doCheckStateChanged(final Object element) {
            //
            // Check all diagrams that are under this element.
            final Widget item = findItem(element);
            if (item instanceof TreeItem) {
                final TreeItem treeItem = (TreeItem) item;
                if (!(element instanceof DDiagram)) {
                    final boolean result = updateChildrenItems(treeItem, treeItem.getChecked());
                    if (result) {
                        treeItem.setGrayed(true);
                    } else {
                        treeItem.setGrayed(false);
                    }
                    treeItem.setChecked(result);
                }
                updateParentItems(treeItem);
            }

        }

        /**
         * Updates the check / gray state of all parent items
         */
        private void updateParentItems(final TreeItem item) {
            if (item != null && !(item.getData() instanceof DDiagram)) {
                final Item[] children = getChildren(item);
                boolean containsChecked = false;
                for (Item element : children) {
                    final TreeItem curr = (TreeItem) element;
                    containsChecked = containsChecked || curr.getChecked();
                }
                item.setChecked(containsChecked);
                item.setGrayed(containsChecked);
            }
            if (item != null) {
                updateParentItems(item.getParentItem());
            }
        }

        /**
         * Updates the check state of all created children
         * 
         * @return <code>true</code> if an element as been checked.
         */
        private boolean updateChildrenItems(final TreeItem parent, final boolean state) {
            boolean result = false;
            final Item[] children = getChildren(parent);
            for (Item element : children) {
                final TreeItem curr = (TreeItem) element;
                if (curr.getData() instanceof DDiagram && ((curr.getChecked() != state) || curr.getGrayed())) {
                    curr.setChecked(state);
                    curr.setGrayed(false);
                    result = result || state;
                    result = result || updateChildrenItems(curr, state);
                } else if (curr.getData() != null && ((curr.getChecked() != state) || curr.getGrayed())) {
                    final boolean childrenResult = updateChildrenItems(curr, state);
                    if (childrenResult) {
                        curr.setChecked(true);
                        curr.setGrayed(true);
                    } else {
                        curr.setChecked(false);
                        curr.setGrayed(false);
                    }
                    result = result || childrenResult;
                }
            }
            return result;
        }
    }

    /**
     * Return all selected elements.
     * 
     * @return all selected elements.
     */
    public Collection<?> getSelectedElements() {
        final Collection<Object> result = new HashSet<Object>();
        result.addAll(Arrays.asList(treeViewer.getCheckedElements()));
        result.removeAll(Arrays.asList(treeViewer.getGrayedElements()));
        return result;
    }

    /**
     * Get the root element.
     * 
     * @return the root element used to create this wizard page
     */
    public DView getRoot() {
        return this.root;
    }

    private static final class SemanticDViewContentProvider implements ICommonContentProvider {

        private static Object[] empty = new Object[0];

        /** The functional analysis to browse. */
        private DView representationContainer;

        /** The semantic EMF content provider. */
        private AdapterFactoryContentProvider semanticProvider;

        /**
         * Create a new <code>SemanticDViewContentProvider</code> with the
         * specified analysis.
         * 
         * @param functionnalAnalysis
         *            the analysis to browse.
         */
        public SemanticDViewContentProvider(final DView functionnalAnalysis) {
            this.representationContainer = functionnalAnalysis;
            final AdapterFactory adapterFactory = new ComposedAdapterFactory(
                    ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
            this.semanticProvider = new AdapterFactoryContentProvider(adapterFactory);
        }

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.ui.navigator.ICommonContentProvider#init(org.eclipse.ui.navigator.ICommonContentExtensionSite)
         */
        public void init(final ICommonContentExtensionSite config) {
            // empty.
        }

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
         */
        public Object[] getChildren(final Object parentElement) {
            if (parentElement instanceof EObject && !(parentElement instanceof DDiagram)) {
                final EObject parent = (EObject) parentElement;
                final Collection<DRepresentation> representations = this.findRepresentations(parent);
                final Object[] semantic = this.semanticProvider.getChildren(parentElement);
                final Object[] result = new Object[representations.size() + semantic.length];
                int i = 0;
                final Iterator<DRepresentation> iterRepresentation = representations.iterator();
                while (iterRepresentation.hasNext()) {
                    result[i++] = iterRepresentation.next();
                }
                System.arraycopy(semantic, 0, result, representations.size(), semantic.length);
                return result;
            }
            return empty;
        }

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
         */
        public Object getParent(final Object element) {
            if (element instanceof EObject) {
                final EObject current = (EObject) element;
                final EObject parent = current instanceof DSemanticDiagram
                        ? ((DSemanticDiagram) current).getTarget()
                        : current.eContainer();
                return parent;
            }
            return null;
        }

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
         */
        public boolean hasChildren(final Object element) {
            return getChildren(element).length > 0;
        }

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
         */
        public Object[] getElements(final Object inputElement) {
            return getChildren(inputElement);
        }

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.jface.viewers.IContentProvider#dispose()
         */
        public void dispose() {
            this.semanticProvider.dispose();
        }

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
         *      java.lang.Object, java.lang.Object)
         */
        public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) {
            // empty
        }

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.ui.navigator.IMementoAware#restoreState(org.eclipse.ui.IMemento)
         */
        public void restoreState(final IMemento memento) {
            // empty.
        }

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.ui.navigator.IMementoAware#saveState(org.eclipse.ui.IMemento)
         */
        public void saveState(final IMemento memento) {
            // empty.
        }

        /**
         * Return all the diagrams for the specified viewpoint.
         * 
         * @param semanticElement
         *            the parent semantic element.
         * @return all the diagrams for the specified viewpoint.
         */
        private Collection<DRepresentation> findRepresentations(final EObject semanticElement) {
            if (semanticElement == null) {
                return Collections.emptySet();
            }
            final Collection<DRepresentation> result = new HashSet<DRepresentation>();
            final Iterator<DRepresentation> itRepresentations = this.representationContainer
                    .getOwnedRepresentations().iterator();
            while (itRepresentations.hasNext()) {
                final DRepresentation representation = itRepresentations.next();
                if (representation instanceof DSemanticDecorator) {
                    if (semanticElement.equals(((DSemanticDecorator) representation).getTarget())) {
                        result.add(representation);
                    }
                }
            }
            return result;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean canFlipToNextPage() {
        return getNextPage() != null;
    }

}