Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCamille Letavernier2018-05-15 07:54:41 +0000
committerNicolas FAUVERGUE2018-05-22 15:58:01 +0000
commitcf83366837c594724208ceaec5a6a9f1a951e352 (patch)
tree309ac55606f46cef6f3d6d41558c84a9f2b4b0f1
parent6abb6f2000f2efe7201bcdf989572fffa302a943 (diff)
downloadorg.eclipse.papyrus-cf83366837c594724208ceaec5a6a9f1a951e352.tar.gz
org.eclipse.papyrus-cf83366837c594724208ceaec5a6a9f1a951e352.tar.xz
org.eclipse.papyrus-cf83366837c594724208ceaec5a6a9f1a951e352.zip
Bug 533684: [Sequence Diagram] Deletion of an InteractionOperand should
resize other InteractionOperand https://bugs.eclipse.org/bugs/show_bug.cgi?id=533684 - Add an advice to propagate the size of an Operand to its sibling operand before deleting it Change-Id: I12dd0f3def082922f5ec674ac8510ee5931ab066 Signed-off-by: Camille Letavernier <cletavernier@eclipsesource.com>
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/helpers/advice/InteractionOperandViewAdvice.java184
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/model/SequenceDiagram.elementtypesconfigurations4
2 files changed, 188 insertions, 0 deletions
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/helpers/advice/InteractionOperandViewAdvice.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/helpers/advice/InteractionOperandViewAdvice.java
new file mode 100644
index 00000000000..f9298f97d59
--- /dev/null
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/helpers/advice/InteractionOperandViewAdvice.java
@@ -0,0 +1,184 @@
+/*****************************************************************************
+ * Copyright (c) 2018 EclipseSource 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:
+ * EclipseSource - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.diagram.sequence.edit.helpers.advice;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.emf.ecore.EStructuralFeature.Setting;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
+import org.eclipse.gmf.runtime.common.core.command.ICommand;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.gmf.runtime.emf.type.core.edithelper.AbstractEditHelperAdvice;
+import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyDependentsRequest;
+import org.eclipse.gmf.runtime.notation.LayoutConstraint;
+import org.eclipse.gmf.runtime.notation.Node;
+import org.eclipse.gmf.runtime.notation.NotationPackage;
+import org.eclipse.gmf.runtime.notation.Size;
+import org.eclipse.gmf.runtime.notation.View;
+import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
+import org.eclipse.papyrus.infra.gmfdiag.common.adapter.NotationAndTypeAdapter;
+import org.eclipse.papyrus.uml.diagram.sequence.command.SetResizeCommand;
+import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.InteractionOperandEditPart;
+import org.eclipse.uml2.uml.InteractionOperand;
+
+/**
+ * <p>
+ * Advice for {@link InteractionOperand} View (InteractionOperand_Shape), responsible
+ * for resize sibling operands during deletion.
+ * </p>
+ * <p>
+ * This advice must be bound before the default GMF's notationDepdendents advice,
+ * to make sure we can propagate the size of the deleted view before it is actually
+ * deleted.
+ * </p>
+ */
+public class InteractionOperandViewAdvice extends AbstractEditHelperAdvice {
+
+ @Override
+ protected ICommand getBeforeDestroyDependentsCommand(DestroyDependentsRequest request) {
+ ICommand beforeDestroyDependentsCommand = super.getBeforeDestroyDependentsCommand(request);
+
+ if (request.getElementToDestroy() instanceof InteractionOperand) {
+ Set<View> operandViews = findOperandViews((InteractionOperand) request.getElementToDestroy());
+ return CompositeCommand.compose(beforeDestroyDependentsCommand,
+ operandViews.stream()
+ .map(view -> getSizeCommandFor(view, request.getEditingDomain()))
+ .reduce(null, CompositeCommand::compose));
+ }
+
+ return beforeDestroyDependentsCommand;
+ }
+
+ private Set<View> findOperandViews(InteractionOperand operand) {
+ return EMFHelper.getUsages(operand).stream()
+ .filter(setting -> setting.getEStructuralFeature() == NotationPackage.Literals.VIEW__ELEMENT)
+ .map(Setting::getEObject)
+ .filter(View.class::isInstance)
+ .map(View.class::cast)
+ .filter(view -> view.getElement() == operand)
+ .filter(view -> InteractionOperandEditPart.VISUAL_ID.equals(view.getType()))
+ .collect(Collectors.toSet());
+ }
+
+ /**
+ * Return the command used to propagate the size of the given <code>viewToDestroy</code>
+ * to one of the sibling operands (The previous one, or the next one if the destroyed view
+ * if the first in the CF).
+ *
+ * The actual resize commands are created on-the-fly during command execution, so
+ * the commands can be properly chained in case of multi-deletion.
+ *
+ * @param viewToDestroy
+ * @param editingDomain
+ * @return
+ */
+ private ICommand getSizeCommandFor(View viewToDestroy, TransactionalEditingDomain editingDomain) {
+ // Do the actual work in the command (At execution time), so we can propagate size changes
+ // in case of multi-selection (So when deleting A, B and C, A will resize B, then B will resize C, then C will resize D)
+ return new AbstractTransactionalCommand(editingDomain, "Resize sibling operand", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
+ Dimension deletedSize = getSize(viewToDestroy);
+ if (deletedSize == null) {
+ return null;
+ }
+ View viewBefore = findViewBefore(viewToDestroy);
+ if (viewBefore != null) {
+ Dimension sizeOfViewBefore = getSize(viewBefore);
+ sizeOfViewBefore.expand(0, deletedSize.height());
+ NotationAndTypeAdapter adapter = new NotationAndTypeAdapter(viewBefore.getElement(), viewBefore);
+ ICommand result = new SetResizeCommand(editingDomain, "Expand previous operand", adapter, sizeOfViewBefore);
+ result.execute(monitor, info);
+ } else {
+ View viewAfter = findViewAfter(viewToDestroy);
+ if (viewAfter != null) {
+ Dimension sizeOfViewAfter = getSize(viewAfter);
+ sizeOfViewAfter.expand(0, deletedSize.height());
+ NotationAndTypeAdapter adapter = new NotationAndTypeAdapter(viewAfter.getElement(), viewAfter);
+ ICommand result = new SetResizeCommand(editingDomain, "Expand previous operand", adapter, sizeOfViewAfter);
+ result.execute(monitor, info);
+ }
+ }
+ return CommandResult.newOKCommandResult();
+ }
+ };
+
+ }
+
+ /**
+ * @param view
+ * @return
+ * The sibling view immediately following the given view, or <code>null</code> if there is no such view
+ */
+ private static View findViewAfter(View view) {
+ if (false == view.eContainer() instanceof View) {
+ return null;
+ }
+
+ List<View> viewSiblings = ((View) view.eContainer()).getPersistedChildren();
+
+ int index = viewSiblings.indexOf(view);
+ int indexAfter = index + 1;
+ if (indexAfter < viewSiblings.size()) {
+ return viewSiblings.get(indexAfter);
+ }
+ return null;
+ }
+
+ /**
+ * @param view
+ * @return
+ * The sibling view immediately preceding the given view, or <code>null</code> if there is no such view
+ */
+ private static View findViewBefore(View view) {
+ if (false == view.eContainer() instanceof View) {
+ return null;
+ }
+
+ List<View> viewSiblings = ((View) view.eContainer()).getPersistedChildren();
+
+ int index = viewSiblings.indexOf(view) - 1;
+
+ if (index >= 0) {
+ return viewSiblings.get(index);
+ }
+ return null;
+ }
+
+ /**
+ * @param view
+ * @return
+ * A new {@link Dimension} instance representing the model size of the {@link View},
+ * or <code>null</code> if the View doesn't have a size.
+ */
+ private Dimension getSize(View view) {
+ if (view instanceof Node) {
+ Node node = (Node) view;
+ LayoutConstraint constraint = node.getLayoutConstraint();
+ if (constraint instanceof Size) {
+ Size size = (Size) constraint;
+ return new Dimension(size.getWidth(), size.getHeight());
+ }
+ }
+ return null;
+ }
+}
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/model/SequenceDiagram.elementtypesconfigurations b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/model/SequenceDiagram.elementtypesconfigurations
index c9a64b7b7b2..bb84ce2dda9 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/model/SequenceDiagram.elementtypesconfigurations
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/model/SequenceDiagram.elementtypesconfigurations
@@ -3,4 +3,8 @@
<adviceBindingsConfigurations xsi:type="elementtypesconfigurations:AdviceBindingConfiguration" xmi:id="_BvoRIENLEeimO7ZhVBpjkg" description="Advice for configuration of the view for the default operand of a new combined fragment." identifier="org.eclipse.papyrus.uml.diagram.sequence.edit.helpers.advice.defaultInteractionOperand" inheritance="all" editHelperAdviceClassName="org.eclipse.papyrus.uml.diagram.sequence.edit.helpers.advice.DefaultInteractionOperandAdvice">
<target xsi:type="elementtypesconfigurations:SpecializationTypeConfiguration" href="platform:/plugin/org.eclipse.papyrus.uml.service.types/model/umldi.elementtypesconfigurations#org.eclipse.papyrus.umldi.CombinedFragment_Shape"/>
</adviceBindingsConfigurations>
+ <adviceBindingsConfigurations xsi:type="elementtypesconfigurations:AdviceBindingConfiguration" xmi:id="_MdNHsFePEeiIR4R5xrPjKA" description="" identifier="org.eclipse.papyrus.uml.diagram.sequence.edit.helpers.advice.interactionoperandviewadvice" inheritance="all" editHelperAdviceClassName="org.eclipse.papyrus.uml.diagram.sequence.edit.helpers.advice.InteractionOperandViewAdvice">
+ <before xsi:type="elementtypesconfigurations:ExternallyRegisteredAdvice" href="platform:/plugin/org.eclipse.papyrus.infra.gmfdiag.common/model/gmfdiag-common.elementtypesconfigurations#_U91U4F6dEeev1-J3e2LKZA"/>
+ <target xsi:type="elementtypesconfigurations:SpecializationTypeConfiguration" href="platform:/plugin/org.eclipse.papyrus.uml.service.types/model/umldi.elementtypesconfigurations#org.eclipse.papyrus.umldi.InteractionOperand_Shape"/>
+ </adviceBindingsConfigurations>
</elementtypesconfigurations:ElementTypeSetConfiguration>

Back to the top