org.eclipse.sirius.diagram.ui.tools.api.layout.PinHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.sirius.diagram.ui.tools.api.layout.PinHelper.java

Source

/*******************************************************************************
 * Copyright (c) 2009 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.layout;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.sirius.diagram.AbstractDNode;
import org.eclipse.sirius.diagram.ArrangeConstraint;
import org.eclipse.sirius.diagram.DDiagram;
import org.eclipse.sirius.diagram.DDiagramElement;
import org.eclipse.sirius.diagram.DDiagramElementContainer;
import org.eclipse.sirius.diagram.DEdge;
import org.eclipse.sirius.diagram.business.api.diagramtype.DiagramTypeDescriptorRegistry;
import org.eclipse.sirius.diagram.business.api.diagramtype.IDiagramDescriptionProvider;
import org.eclipse.sirius.diagram.business.api.diagramtype.IDiagramTypeDescriptor;
import org.eclipse.sirius.diagram.business.internal.query.DDiagramElementContainerExperimentalQuery;
import org.eclipse.sirius.diagram.ui.edit.api.part.IDiagramElementEditPart;

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;

/**
 * Helper class to test and manipulate the "pinned" status of
 * {@link DDiagramElement}.
 * 
 * @author pcdavid
 * 
 * @since 0.9.0
 */
public final class PinHelper {

    /**
     * Set of {@link ArrangeConstraint} to specify pinned
     * {@link DDiagramElement}.
     */
    public static final Collection<ArrangeConstraint> PINNED_CONSTRAINTS = new ArrayList<ArrangeConstraint>();

    static {
        PINNED_CONSTRAINTS.add(ArrangeConstraint.KEEP_LOCATION);
        PINNED_CONSTRAINTS.add(ArrangeConstraint.KEEP_SIZE);
        PINNED_CONSTRAINTS.add(ArrangeConstraint.KEEP_RATIO);
    }

    /**
     * Get the pinned status of the {@link DDiagramElement} associated to this
     * {@link IDiagramElementEditPart} <code>self</code>.
     * 
     * @param self
     *            the edit part from which to test the pinned status of the
     *            associated {@link DDiagramElement}.
     * 
     * @return <code>true</code> if the associated {@link DDiagramElement} is
     *         pinned, false else.
     * 
     * @see {@link PinHelper#isPinned(DDiagramElement)}
     */
    public boolean isPinned(final IDiagramElementEditPart self) {
        boolean isPinned = false;
        EObject diagramElement = self.resolveDiagramElement();
        if (diagramElement instanceof DDiagramElement) {
            DDiagramElement dDiagramElement = (DDiagramElement) diagramElement;
            isPinned = isPinned(dDiagramElement);
        }
        return isPinned;
    }

    /**
     * Get the pinned status of the {@link DDiagramElement}
     * <code>dDiagramElement</code>. The pinned status is defined by having the
     * following {@link ArrangeConstraint} through
     * {@link AbstractDNode#getArrangeConstraints()} or
     * {@link DEdge#getArrangeConstraints()} :
     * 
     * <ol>
     * <li>
     * {@link ArrangeConstraint#KEEP_LOCATION}</li>
     * <li>
     * {@link ArrangeConstraint#KEEP_SIZE}</li>
     * <li>
     * {@link ArrangeConstraint#KEEP_RATIO}</li>
     * </ol>
     * 
     * @param dDiagramElement
     *            the {@link DDiagramElement} from which to test the pinned
     *            status.
     * 
     * @return <code>true</code> if the associated {@link DDiagramElement} is
     *         pinned, false else.
     */
    public boolean isPinned(final DDiagramElement dDiagramElement) {
        boolean isPinned = false;
        List<ArrangeConstraint> constraints = getArrangeConstraints(dDiagramElement);
        isPinned = constraints != null && constraints.containsAll(PINNED_CONSTRAINTS);
        return isPinned;
    }

    /**
     * Mark a {@link DDiagramElement} as pinned if possible (depending on its
     * actual type : {@link AbstractDNode} or {@link DEdge}).
     * 
     * @param dDiagramElement
     *            the {@link DDiagramElement} to pin
     * 
     * @return <code>true</code> if <code>dDiagramElement</code> has been
     *         pinned, <code>false</code> if it could not
     */
    public boolean markAsPinned(DDiagramElement dDiagramElement) {
        boolean pinned = false;
        List<ArrangeConstraint> constraints = getArrangeConstraints(dDiagramElement);
        if (constraints != null) {
            constraints.addAll(PINNED_CONSTRAINTS);
            pinned = true;
        }
        return pinned;
    }

    /**
     * Mark a {@link DDiagramElement} as un-pinned if possible (depending on its
     * actual type : {@link AbstractDNode} or {@link DEdge}).
     * 
     * @param dDiagramElement
     *            the {@link DDiagramElement} to un-pin
     * 
     * @return <code>true</code> if the <code>dDiagramElement</code> was
     *         un-pinned, <code>false</code> if it could not
     */
    public boolean markAsUnpinned(DDiagramElement dDiagramElement) {
        boolean pinned = false;
        List<ArrangeConstraint> constraints = getArrangeConstraints(dDiagramElement);
        if (constraints != null) {
            constraints.removeAll(PINNED_CONSTRAINTS);
            pinned = true;
        }
        return pinned;
    }

    private List<ArrangeConstraint> getArrangeConstraints(final EObject diagramElement) {
        List<ArrangeConstraint> constraints = null;
        if (diagramElement instanceof AbstractDNode) {
            final AbstractDNode node = (AbstractDNode) diagramElement;
            constraints = node.getArrangeConstraints();
        } else if (diagramElement instanceof DEdge) {
            final DEdge edge = (DEdge) diagramElement;
            constraints = edge.getArrangeConstraints();
        }
        return constraints;
    }

    /**
     * Indicates if the given element can be pinned/unpinned.
     * 
     * @param element
     *            the element to check.
     * @return true if the given element can be pinned/unpinned.
     */
    public static boolean allowsPinUnpin(DDiagramElement element) {
        return element != null && allowsPinUnpin(element.getParentDiagram()).apply(element);
    }

    /**
     * Indicates if the given ddiagram is allowing pin/unpin.
     * 
     * @param diagram
     *            the diagram to inspect
     * @return true if the given ddiagram is allowing layouting mode, false
     *         otherwise
     */
    private static Predicate<DDiagramElement> allowsPinUnpin(DDiagram diagram) {
        // default return value is true for non-Region element (for basic
        // DDiagram that are not handled
        // by any DiagramDescriptionProvider).
        Predicate<DDiagramElement> result = new Predicate<DDiagramElement>() {
            public boolean apply(DDiagramElement dde) {
                if (dde instanceof DDiagramElementContainer) {
                    DDiagramElementContainerExperimentalQuery query = new DDiagramElementContainerExperimentalQuery(
                            (DDiagramElementContainer) dde);
                    return !query.isRegion();
                }
                return true;
            }
        };

        // If an aird has been opened from the Package Explorer View, then
        // we return false as no diagram is associated to this editor
        if (diagram == null || diagram.getDescription() == null) {
            return Predicates.alwaysFalse();
        }

        // If diagram is not null, we search for a possible
        // DiagramDescriptionProvider handling this type of diagram
        for (final IDiagramTypeDescriptor diagramTypeDescriptor : DiagramTypeDescriptorRegistry.getInstance()
                .getAllDiagramTypeDescriptors()) {
            if (diagramTypeDescriptor.getDiagramDescriptionProvider()
                    .handles(diagram.getDescription().eClass().getEPackage())) {
                // This DiagramDescriptionProvider may forbid pin/unpin actions.
                final IDiagramDescriptionProvider provider = diagramTypeDescriptor.getDiagramDescriptionProvider();
                result = new Predicate<DDiagramElement>() {
                    @Override
                    public boolean apply(DDiagramElement input) {
                        return provider.allowsPinUnpin(input);
                    }
                };
                break;
            }
        }

        return result;
    }

}