Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: d7195c7150ebc851d19441dd1683e8e24169e520 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/*******************************************************************************
 * Copyright (c) 2012 CEA LIST.
 *
 * 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
 *******************************************************************************/
package org.eclipse.papyrus.uml.diagram.timing.custom.edit.commands;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
import org.eclipse.gmf.runtime.notation.Location;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.NotationFactory;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.uml.diagram.timing.custom.Messages;
import org.eclipse.papyrus.uml.diagram.timing.custom.utils.EditPartUtils;
import org.eclipse.papyrus.uml.diagram.timing.custom.utils.LifelineUtils;
import org.eclipse.papyrus.uml.diagram.timing.custom.utils.OccurrenceSpecificationUtils;
import org.eclipse.papyrus.uml.diagram.timing.custom.utils.StateInvariantUtils;
import org.eclipse.papyrus.uml.diagram.timing.custom.utils.ViewUtils;
import org.eclipse.papyrus.uml.diagram.timing.edit.parts.CompactLifelineCompartmentEditPartCN;
import org.eclipse.papyrus.uml.diagram.timing.edit.parts.CompactLifelineEditPartCN;
import org.eclipse.papyrus.uml.diagram.timing.edit.parts.CompactStateInvariantEditPartCN;
import org.eclipse.papyrus.uml.diagram.timing.providers.UMLViewProvider;
import org.eclipse.swt.widgets.Display;
import org.eclipse.uml2.uml.Lifeline;
import org.eclipse.uml2.uml.OccurrenceSpecification;
import org.eclipse.uml2.uml.StateInvariant;
import org.eclipse.uml2.uml.UMLFactory;

/**
 * This command cuts a StateInvariant in two StateInvariants, with an OccurrenceSpecification in between the two
 * StateInvariants.
 */
public class CutAndInsertOccurrenceSpecificationCompactLifelineCommand extends AbstractTransactionalCommand {

	private final CompactStateInvariantEditPartCN compactStateInvariantEditPartCN;

	private final Point location;

	private final CompactLifelineEditPartCN lifelineEditPart;

	private final Lifeline lifeline;

	private final boolean destruction;

	/**
	 * @param fullStateInvariantEditPartCN
	 *        the state invariant to cut in two
	 * @param location
	 *        where the user clicked: the horizontal coordinate indicates where to insert the
	 *        OccurrenceSpecification
	 * @param destruction
	 *        whether to create a DestructionOccurrenceSpecification
	 */
	public CutAndInsertOccurrenceSpecificationCompactLifelineCommand(final CompactStateInvariantEditPartCN compactStateInvariantEditPartCN, final Point location, final boolean destruction) {
		super(getEditingDomain(compactStateInvariantEditPartCN), Messages.CutAndInsertOccurrenceSpecificationCompactLifelineCommand_CreateOccurrenceSpecification, null);
		this.compactStateInvariantEditPartCN = compactStateInvariantEditPartCN;
		this.location = location;
		this.destruction = destruction;
		this.lifelineEditPart = (CompactLifelineEditPartCN)EditPartUtils.findParentEditPartWithId(this.compactStateInvariantEditPartCN, CompactLifelineEditPartCN.VISUAL_ID);
		this.lifeline = (Lifeline)((View)this.lifelineEditPart.getModel()).getElement();
	}

	private static TransactionalEditingDomain getEditingDomain(final CompactStateInvariantEditPartCN compactStateInvariantEditPart) {
		final StateInvariant stateInvariant = (StateInvariant)((View)compactStateInvariantEditPart.getModel()).getElement();
		return TransactionUtil.getEditingDomain(stateInvariant);
	}

	@Override
	protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
		final CompactLifelineCompartmentEditPartCN timelineCompartmentEditPart = (CompactLifelineCompartmentEditPartCN)EditPartUtils.findFirstChildEditPartWithId(this.lifelineEditPart, CompactLifelineCompartmentEditPartCN.VISUAL_ID);

		final View timelineCompartmentView = (View)timelineCompartmentEditPart.getModel();

		// translate the coordinates
		final Point pt = new Point(this.location);
		timelineCompartmentEditPart.getFigure().translateToRelative(pt);
		pt.translate(timelineCompartmentEditPart.getFigure().getBounds().getTopLeft().getNegated());

		// find where to insert the OccurrenceSpecification
		int insertionIndexInCompartment = OccurrenceSpecificationUtils.findInsertionIndexFor(pt, timelineCompartmentView, timelineCompartmentEditPart.getViewer());
		int insertionIndexInFragments;
		int insertionIndexInCoveredBys;
		if(insertionIndexInCompartment < timelineCompartmentView.getChildren().size()) {
			final View view = (View)timelineCompartmentView.getChildren().get(insertionIndexInCompartment);
			final EObject element = view.getElement();
			insertionIndexInFragments = this.lifeline.getInteraction().getFragments().indexOf(element);
			insertionIndexInCoveredBys = this.lifeline.getCoveredBys().indexOf(element);
		} else {
			insertionIndexInFragments = -1;
			insertionIndexInCoveredBys = -1;
		}

		// create the occurrence specification at the right index
		final OccurrenceSpecification newOccurrenceSpecification = this.destruction ? UMLFactory.eINSTANCE.createDestructionOccurrenceSpecification() : UMLFactory.eINSTANCE.createOccurrenceSpecification();
		OccurrenceSpecificationUtils.setAutogeneratedName(newOccurrenceSpecification, true);
		if(insertionIndexInFragments == -1) {
			this.lifeline.getInteraction().getFragments().add(newOccurrenceSpecification);
		} else {
			this.lifeline.getInteraction().getFragments().add(insertionIndexInFragments, newOccurrenceSpecification);
		}
		if(insertionIndexInCoveredBys == -1) {
			this.lifeline.getCoveredBys().add(newOccurrenceSpecification);
		} else {
			this.lifeline.getCoveredBys().add(insertionIndexInCoveredBys, newOccurrenceSpecification);
		}

		// create the View for the occurrence specification
		final UMLViewProvider umlViewProvider = new UMLViewProvider();

		final Node occurrenceSpecificationView;
		if(this.destruction) {
			occurrenceSpecificationView = umlViewProvider.createDestructionOccurrenceSpecification_27(newOccurrenceSpecification, timelineCompartmentView, insertionIndexInCompartment, true, PreferencesHint.USE_DEFAULTS);
		} else {
			occurrenceSpecificationView = umlViewProvider.createOccurrenceSpecification_12(newOccurrenceSpecification, timelineCompartmentView, insertionIndexInCompartment, true, PreferencesHint.USE_DEFAULTS);
		}

		final Location loc = NotationFactory.eINSTANCE.createLocation();
		loc.setX(pt.x);
		loc.setY(pt.y);
		occurrenceSpecificationView.setLayoutConstraint(loc);

		if(this.destruction) {
			OccurrenceSpecificationUtils.deleteEverythingAfter(newOccurrenceSpecification, occurrenceSpecificationView);
		} else {
			// increase the indices for inserting the state invariant (don't increase -1 since it means "at the end")
			if(insertionIndexInFragments != -1) {
				insertionIndexInFragments++;
			}
			if(insertionIndexInCoveredBys != -1) {
				insertionIndexInCoveredBys++;
			}
			if(insertionIndexInCompartment != -1) {
				insertionIndexInCompartment++;
			}

			// create a new state invariant
			StateInvariantUtils.createCompactStateInvariant(timelineCompartmentView, insertionIndexInFragments, insertionIndexInCoveredBys, insertionIndexInCompartment);
		}

		LifelineUtils.updateFragmentNames(this.lifeline, null);

		Display.getDefault().asyncExec(new Runnable() {

			public void run() {
				timelineCompartmentEditPart.refresh();
				ViewUtils.selectInViewer(occurrenceSpecificationView, CutAndInsertOccurrenceSpecificationCompactLifelineCommand.this.lifelineEditPart.getViewer());
			}
		});

		return CommandResult.newOKCommandResult(newOccurrenceSpecification);
	}

}

Back to the top