org.eclipse.sirius.ui.business.internal.viewpoint.ViewpointSelectionDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.sirius.ui.business.internal.viewpoint.ViewpointSelectionDialog.java

Source

/*******************************************************************************
 * Copyright (c) 2014, 2016 THALES GLOBAL SERVICES 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:
 *    Obeo - initial API and implementation
 *******************************************************************************/
package org.eclipse.sirius.ui.business.internal.viewpoint;

import java.text.MessageFormat;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.DecorationOverlayIcon;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IDecoration;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.sirius.business.api.componentization.ViewpointRegistry;
import org.eclipse.sirius.business.api.query.IdentifiedElementQuery;
import org.eclipse.sirius.business.api.query.ViewpointQuery;
import org.eclipse.sirius.common.tools.api.util.MessageTranslator;
import org.eclipse.sirius.ext.base.Option;
import org.eclipse.sirius.viewpoint.description.RepresentationExtensionDescription;
import org.eclipse.sirius.viewpoint.description.Viewpoint;
import org.eclipse.sirius.viewpoint.provider.Messages;
import org.eclipse.sirius.viewpoint.provider.SiriusEditPlugin;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;

import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;

/**
 * A dialog box which allow end-users to select which viewpoints are enabled
 * inside a session.
 * 
 * @author <a href="mailto:mickael.lanoe@obeo.fr">Mickael LANOE</a>
 */
public class ViewpointSelectionDialog extends TitleAreaDialog {
    private static final String VIEWPOINT_SELECTION_SHELL_TITLE = Messages.ViewpointSelectionDialog_title;

    private static final String VIEWPOINT_SELECTION_TITLE = Messages.ViewpointSelectionDialog_dialogTitle;

    private static final String VIEWPOINT_SELECTION_MESSAGE = Messages.ViewpointSelectionDialog_selectionMessage;

    /**
     * Table item
     */
    private final class Item {
        private final Viewpoint viewpoint;

        /**
         * Construct from a viewpoint
         * 
         * @param vp
         *            the viewpoint
         */
        public Item(Viewpoint vp) {
            this.viewpoint = vp;
        }

        /**
         * Get the item label
         * 
         * @return viewpoint name
         */
        public String getLabel() {
            return MessageTranslator.INSTANCE.getMessage(viewpoint,
                    new IdentifiedElementQuery(viewpoint).getLabel());
        }

        /**
         * Select the viewpoint corresponding to this element.
         */
        public void onChecked() {
            // add to the selection
            selection.put(this.viewpoint, true);
        }

        /**
         * Deselect the viewpoint.
         */
        public void onUnchecked() {
            // remove from the selection
            selection.put(this.viewpoint, false);
        }

        /**
         * Convert to string
         * 
         * @return the label
         */
        @Override
        public String toString() {
            return this.getLabel();
        }

        /**
         * Get the viewpoint
         * 
         * @return the viewpoint
         */
        public Viewpoint getViewpoint() {
            return viewpoint;
        }

        /**
         * Compute state
         */
        public void computeState() {
            table.setChecked(this, isSelected());
        }

        /**
         * Returns true if the viewpoint is selected
         * 
         * @return true if the viewpoint is selected
         */
        private boolean isSelected() {
            return Boolean.TRUE.equals(selection.get(this.viewpoint));
        }
    } // class

    /**
     * Viewpoint table content provider.
     */
    private final class TableContentProvider implements IStructuredContentProvider {
        @Override
        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            // Ignore.
        }

        @Override
        public void dispose() {
            // Ignore.
        }

        @Override
        public Object[] getElements(Object inputElement) {
            if (inputElement instanceof List<?>
                    && Iterables.all((List<?>) inputElement, Predicates.instanceOf(Item.class))) {
                @SuppressWarnings("unchecked")
                List<Item> topItems = (List<Item>) inputElement;
                return topItems.toArray();
            } else {
                return null;
            }
        }
    } // class

    /**
     * Viewpoint table label provider
     */
    private final class TableLabelProvider extends ColumnLabelProvider {
        @Override
        public Image getImage(final Object element) {
            Item item = (Item) element;

            Image viewpointImage = null;
            Viewpoint vp = item.getViewpoint();
            if (vp.getIcon() != null && vp.getIcon().length() > 0) {
                final ImageDescriptor desc = SiriusEditPlugin.Implementation.findImageDescriptor(vp.getIcon());
                if (desc != null) {
                    viewpointImage = SiriusEditPlugin.getPlugin().getImage(desc);
                }
            }
            // Default image
            if (viewpointImage == null) {
                viewpointImage = SiriusEditPlugin.getPlugin()
                        .getImage(SiriusEditPlugin.getPlugin().getItemImageDescriptor(vp));
            }

            // Add decorator if the viewpoint comes from workspace
            if (!ViewpointRegistry.getInstance().isFromPlugin(vp)) {
                final ImageDescriptor decoratorDescriptor = SiriusEditPlugin.Implementation
                        .getBundledImageDescriptor("icons/full/decorator/folder_close.gif"); //$NON-NLS-1$
                viewpointImage = SiriusEditPlugin.getPlugin().getImage(
                        new DecorationOverlayIcon(viewpointImage, decoratorDescriptor, IDecoration.BOTTOM_LEFT));
            }
            return viewpointImage;
        }

        @Override
        public String getText(final Object element) {
            Item item = (Item) element;
            return item.getLabel();
        }

        @Override
        public String getToolTipText(Object element) {
            Item item = (Item) element;

            String toolTip = ""; // no null //$NON-NLS-1$
            Viewpoint viewpoint = item.getViewpoint();
            final Resource resource = viewpoint.eResource();
            if (resource != null) {
                toolTip = resource.getURI().toString();
            }

            if (viewpoint.getEndUserDocumentation() != null) {
                String doc = viewpoint.getEndUserDocumentation().trim();
                if (!doc.isEmpty()) {
                    if (!toolTip.isEmpty()) {
                        toolTip += "\n\n"; //$NON-NLS-1$
                    }

                    toolTip += doc;
                }
            }

            return toolTip;
        }

        @Override
        public Point getToolTipShift(final Object object) {
            return new Point(5, 5);
        }

        @Override
        public int getToolTipDisplayDelayTime(final Object object) {
            return 200;
        }

        @Override
        public int getToolTipStyle(final Object object) {
            return SWT.SHADOW_OUT;
        }
    } // class

    /**
     * Viewpoint table check state listener
     */
    private final class TableCheckStateListener implements ICheckStateListener {
        @Override
        public void checkStateChanged(CheckStateChangedEvent event) {
            if (event.getElement() instanceof Item) {
                Item item = (Item) event.getElement();
                if (event.getChecked()) {
                    item.onChecked();
                } else {
                    item.onUnchecked();
                }

                Map<String, Collection<String>> missingDependencies = getMissingDependencies();

                if (!missingDependencies.isEmpty()) {
                    String message = getMissingDependenciesErrorMessage(missingDependencies);
                    setErrorMessage(message);
                } else {
                    setErrorMessage(null);
                }

                getButton(IDialogConstants.OK_ID).setEnabled(missingDependencies.isEmpty());
            }
        }
    } // class

    private CheckboxTableViewer table;

    private final Map<Viewpoint, Boolean> selection;

    private final List<Item> input;

    /**
     * Constructor.
     * 
     * @param parentShell
     *            the parent shell for the dialog box.
     * @param selection
     *            the selection of viewpoints (this list is not modified).
     */
    public ViewpointSelectionDialog(Shell parentShell, Map<Viewpoint, Boolean> selection) {
        super(parentShell);

        // CHECKSTYLE:OFF Boolean expression complexity is 5 (max allowed is 3).
        setShellStyle(SWT.CLOSE | SWT.MAX | SWT.TITLE | SWT.BORDER | SWT.APPLICATION_MODAL | SWT.RESIZE);
        // CHECKSTYLE:ON

        // clone the selection in order to modify it
        final SortedMap<Viewpoint, Boolean> newSelection = Maps
                .newTreeMap(new ViewpointRegistry.ViewpointComparator());
        newSelection.putAll(Preconditions.checkNotNull(selection));
        this.selection = newSelection;

        // item list
        this.input = computeItemList();

        // block on open
        setBlockOnOpen(true);
    }

    /**
     * Get the current selection. This selection contains user modification
     * 
     * @return the current selection
     */
    public Map<Viewpoint, Boolean> getSelection() {
        return selection;
    }

    /**
     * Compute the list of items.
     * 
     * @return the new list of items
     */
    private List<Item> computeItemList() {
        return Lists.newArrayList(Iterables.transform(selection.keySet(), new Function<Viewpoint, Item>() {
            @Override
            public Item apply(Viewpoint from) {
                return new Item(from);
            }
        }));
    }

    @Override
    protected Control createContents(Composite parent) {
        Control contents = super.createContents(parent);
        setTitle(VIEWPOINT_SELECTION_TITLE);
        setMessage(VIEWPOINT_SELECTION_MESSAGE);
        Shell shell = parent.getShell();
        shell.setText(VIEWPOINT_SELECTION_SHELL_TITLE);
        shell.pack();
        return contents;
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        Composite composite = (Composite) super.createDialogArea(parent);
        composite.setLayout(new GridLayout(1, false));

        table = CheckboxTableViewer.newCheckList(composite, SWT.BORDER | SWT.FULL_SELECTION);
        ColumnViewerToolTipSupport.enableFor(table, ToolTip.NO_RECREATE);
        table.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        table.setContentProvider(new TableContentProvider());
        table.setLabelProvider(new TableLabelProvider());
        table.addCheckStateListener(new TableCheckStateListener());
        table.setInput(input);

        for (Item item : input) {
            item.computeState();
        }

        return composite;
    }

    /**
     * Get missing dependencies from the current selection
     * 
     * @return missing dependencies
     */
    private Map<String, Collection<String>> getMissingDependencies() {
        Set<Viewpoint> selected = Maps.filterValues(selection, Predicates.equalTo(Boolean.TRUE)).keySet();

        Multimap<String, String> result = HashMultimap.create();
        for (Viewpoint viewpoint : selected) {
            for (RepresentationExtensionDescription extension : new ViewpointQuery(viewpoint)
                    .getAllRepresentationExtensionDescriptions()) {
                String extended = extension.getViewpointURI();
                final Pattern pattern = Pattern.compile(extended);

                // Is there at least one available selected viewpoint URI ?
                if (!Iterables.any(selected, new Predicate<Viewpoint>() {
                    @Override
                    public boolean apply(Viewpoint vp) {
                        Option<URI> uri = new ViewpointQuery(vp).getViewpointURI();
                        if (uri.some()) {
                            Matcher matcher = pattern.matcher(uri.get().toString());
                            return matcher.matches();
                        } else {
                            return false;
                        }
                    }
                })) {
                    result.put(viewpoint.getName(), extended.trim().replaceFirst("^viewpoint:/[^/]+/", "")); //$NON-NLS-1$ //$NON-NLS-2$
                }
            }
        }
        return result.asMap();
    }

    /**
     * Compute error message from missing dependencies
     * 
     * @param missingDependencies
     *            missing dependencies
     * @return error message
     */
    private static String getMissingDependenciesErrorMessage(Map<String, Collection<String>> missingDependencies) {
        final Function<Collection<String>, String> toStringList = new Function<Collection<String>, String>() {
            @Override
            public String apply(java.util.Collection<String> from) {
                return Joiner.on(", ").join(from); //$NON-NLS-1$
            }
        };
        return Joiner.on("\n").join(Iterables.transform(missingDependencies.entrySet(), //$NON-NLS-1$
                new Function<Map.Entry<String, Collection<String>>, String>() {
                    @Override
                    public String apply(Entry<String, Collection<String>> entry) {
                        return MessageFormat.format(Messages.ViewpointSelection_missingDependencies_requirements,
                                entry.getKey(), toStringList.apply(entry.getValue()));
                    }
                }));
    }

}