org.eclipse.sirius.diagram.ui.graphical.edit.policies.SiriusContainerEditPolicy.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.sirius.diagram.ui.graphical.edit.policies.SiriusContainerEditPolicy.java

Source

/*******************************************************************************
 * Copyright (c) 2002, 2015 IBM Corporation 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:
 *    IBM Corporation - initial API and implementation 
 *    Obeo - Adaptations.
 *******************************************************************************/

package org.eclipse.sirius.diagram.ui.graphical.edit.policies;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gef.requests.GroupRequest;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.common.core.util.ObjectAdapter;
import org.eclipse.gmf.runtime.common.core.util.StringStatics;
import org.eclipse.gmf.runtime.diagram.ui.actions.ActionIds;
import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.commands.DeferredLayoutCommand;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.ContainerEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.internal.properties.WorkspaceViewerProperties;
import org.eclipse.gmf.runtime.diagram.ui.internal.services.layout.IInternalLayoutRunnable;
import org.eclipse.gmf.runtime.diagram.ui.internal.services.layout.LayoutNode;
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramGraphicalViewer;
import org.eclipse.gmf.runtime.diagram.ui.requests.ArrangeRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants;
import org.eclipse.gmf.runtime.diagram.ui.services.layout.LayoutType;
import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDiagramElementContainerEditPart;
import org.eclipse.sirius.diagram.ui.internal.edit.commands.CenterEdgeLayoutCommand;
import org.eclipse.sirius.diagram.ui.internal.edit.commands.DistributeCommand;
import org.eclipse.sirius.diagram.ui.tools.api.requests.DistributeRequest;
import org.eclipse.sirius.diagram.ui.tools.internal.commands.SnapCommand;
import org.eclipse.sirius.diagram.ui.tools.internal.ui.GMFRuntimeCompatibility;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;

/**
 * A specific class to override the arrangeCommand for the GMF runtime version
 * older that 1.4.0.<BR>
 * This class launches the arrange even for one element.
 * 
 * @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a>
 * 
 */
public class SiriusContainerEditPolicy extends ContainerEditPolicy {

    private final Predicate<Object> isRegionEditPart = new Predicate<Object>() {
        @Override
        public boolean apply(Object input) {
            return input instanceof AbstractDiagramElementContainerEditPart
                    && ((AbstractDiagramElementContainerEditPart) input).isRegion();
        }
    };

    @Override
    public Command getCommand(Request request) {
        if (org.eclipse.sirius.diagram.ui.tools.api.requests.RequestConstants.REQ_DISTRIBUTE
                .equals(request.getType())) {
            return getDistributeCommand((DistributeRequest) request);
        }

        return super.getCommand(request);
    }

    // CHECKSTYLE:OFF
    /**
     * Override this method for version before GMF 1.5.0 with Eclipse 3.6.
     * Indeed, in the previous version there is a test that launch arrange only
     * with more that one element. But we want to launch arrange even with one
     * element to have always the same result (one or more new elements) : to
     * avoid overlaps with pinned elements for example.<BR>
     * {@inheritDoc}
     * 
     * @see org.eclipse.gmf.runtime.diagram.ui.editpolicies.ContainerEditPolicy#getArrangeCommand(org.eclipse.gmf.runtime.diagram.ui.requests.ArrangeRequest)
     */
    @Override
    protected Command getArrangeCommand(ArrangeRequest request) {
        Command commandToReturn = null;
        if (GMFRuntimeCompatibility.hasGMFPluginReleaseBetween1_2_0_And_1_3_3()) {
            if (RequestConstants.REQ_ARRANGE_DEFERRED.equals(request.getType())) {
                String layoutType = request.getLayoutType();
                TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost()).getEditingDomain();
                return new ICommandProxy(new DeferredLayoutCommand(editingDomain,
                        request.getViewAdaptersToArrange(), (IGraphicalEditPart) getHost(), layoutType));
            }

            String layoutDesc = request.getLayoutType() != null ? request.getLayoutType() : LayoutType.DEFAULT;
            boolean offsetFromBoundingBox = false;
            List editparts = new ArrayList();

            if ((ActionIds.ACTION_ARRANGE_ALL.equals(request.getType()))
                    || (ActionIds.ACTION_TOOLBAR_ARRANGE_ALL.equals(request.getType()))) {
                editparts = ((IGraphicalEditPart) getHost()).getChildren();
                request.setPartsToArrange(editparts);
            }
            if ((ActionIds.ACTION_ARRANGE_SELECTION.equals(request.getType()))
                    || (ActionIds.ACTION_TOOLBAR_ARRANGE_SELECTION.equals(request.getType()))) {
                editparts = request.getPartsToArrange();
                // Just comment this line to launch an arrange command even with
                // one elemnt
                // if (editparts.size() < 2
                // || !(((GraphicalEditPart) ((EditPart) editparts.get(0))
                // .getParent()).getContentPane().getLayoutManager() instanceof
                // XYLayout)) {
                // return null;
                // }
                offsetFromBoundingBox = true;
            }
            if (RequestConstants.REQ_ARRANGE_RADIAL.equals(request.getType())) {
                editparts = request.getPartsToArrange();
                offsetFromBoundingBox = true;
                layoutDesc = LayoutType.RADIAL;
            }
            if (editparts.isEmpty())
                return null;
            List nodes = new ArrayList(editparts.size());
            ListIterator li = editparts.listIterator();
            while (li.hasNext()) {
                IGraphicalEditPart ep = (IGraphicalEditPart) li.next();
                View view = ep.getNotationView();
                if (ep.isActive() && view instanceof Node) {
                    Rectangle bounds = ep.getFigure().getBounds();
                    nodes.add(new LayoutNode((Node) view, bounds.width, bounds.height));
                }
            }
            if (nodes.isEmpty()) {
                return null;
            }

            List hints = new ArrayList(2);
            hints.add(layoutDesc);
            hints.add(getHost());
            IAdaptable layoutHint = new ObjectAdapter(hints);
            final Runnable layoutRun = layoutNodes(nodes, offsetFromBoundingBox, layoutHint);

            boolean isSnap = true;
            // retrieves the preference store from the first edit part
            IGraphicalEditPart firstEditPart = (IGraphicalEditPart) editparts.get(0);
            if (firstEditPart.getViewer() instanceof DiagramGraphicalViewer) {
                IPreferenceStore preferenceStore = ((DiagramGraphicalViewer) firstEditPart.getViewer())
                        .getWorkspaceViewerPreferenceStore();
                if (preferenceStore != null) {
                    isSnap = preferenceStore.getBoolean(WorkspaceViewerProperties.SNAPTOGRID);
                }
            }

            // the snapCommand still invokes proper calculations if snap to grid
            // is turned off, this additional check
            // is intended to make the code more appear more logical

            TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost()).getEditingDomain();
            CompositeTransactionalCommand ctc = new CompositeTransactionalCommand(editingDomain,
                    StringStatics.BLANK);
            if (layoutRun instanceof IInternalLayoutRunnable) {
                ctc.add(new CommandProxy(((IInternalLayoutRunnable) layoutRun).getCommand()));
            } else {
                ctc.add(new AbstractTransactionalCommand(editingDomain, StringStatics.BLANK, null) {
                    @Override
                    protected CommandResult doExecuteWithResult(IProgressMonitor progressMonitor, IAdaptable info)
                            throws ExecutionException {
                        layoutRun.run();
                        return CommandResult.newOKCommandResult();
                    }
                });
            }
            if (isSnap) {
                Command snapCmd = getSnapCommand(request);
                if (snapCmd != null) {
                    ctc.add(new CommandProxy(getSnapCommand(request)));
                }
            }
            commandToReturn = new ICommandProxy(ctc);
        } else {
            commandToReturn = super.getArrangeCommand(request);
        }

        if ((ActionIds.ACTION_ARRANGE_SELECTION.equals(request.getType()))
                || (ActionIds.ACTION_TOOLBAR_ARRANGE_SELECTION.equals(request.getType()))) {
            if (Iterables.any(request.getPartsToArrange(), isRegionEditPart)) {
                return UnexecutableCommand.INSTANCE;
            }
        }

        // We add a Command to center edges that need to be at the end of the
        // layout.
        if (commandToReturn != null) {
            EditPart host = getHost();
            if (host instanceof GraphicalEditPart) {
                CenterEdgeLayoutCommand centerEdgeLayoutCommand = new CenterEdgeLayoutCommand(
                        (GraphicalEditPart) host);
                commandToReturn = commandToReturn.chain(new ICommandProxy(centerEdgeLayoutCommand));
            }
        }
        return commandToReturn;
    }

    /**
     * Duplicates method from
     * {@link org.eclipse.gmf.runtime.diagram.ui.editpolicies.ContainerEditPolicy}
     * for the duplication of getArrangeCommand.
     * 
     * @param request
     *            The current request.
     * @return A command to snap the edit parts of the request.
     */
    private Command getSnapCommand(Request request) {

        List editparts = null;
        if (request instanceof GroupRequest) {
            editparts = ((GroupRequest) request).getEditParts();
        } else if (request instanceof ArrangeRequest) {
            editparts = ((ArrangeRequest) request).getPartsToArrange();
        }

        TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost()).getEditingDomain();
        if (editparts != null) {
            return new ICommandProxy(new SnapCommand(editingDomain, editparts));
        }
        return null;
    }

    // CHECKSTYLE:ON

    /**
     * Gets a distribute command.
     * 
     * @param request
     *            The distribute request
     * @return command
     */
    protected Command getDistributeCommand(DistributeRequest request) {
        List<IGraphicalEditPart> editparts = request.getEditParts();
        if (!editparts.isEmpty() && getHost() instanceof IGraphicalEditPart) {
            return new ICommandProxy(new DistributeCommand(((IGraphicalEditPart) getHost()).getEditingDomain(),
                    editparts, request.getDistributeType()));
        }
        return null;
    }
}