Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 63aecb6e4d309343fb6b03d5cf3faa790256720c (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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/*****************************************************************************
 * Copyright (c) 2018 CEA LIST, EclipseSource and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *   EclipseSource - Initial API and implementation
 *
 *****************************************************************************/

package org.eclipse.papyrus.uml.diagram.sequence.edit.policies;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.ConnectionLocator;
import org.eclipse.draw2d.Cursors;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.DragTracker;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.Handle;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.handles.ConnectionHandle;
import org.eclipse.gef.handles.SquareHandle;
import org.eclipse.gef.tools.SelectEditPartTracker;
import org.eclipse.gef.tools.SimpleDragTracker;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart;
import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
import org.eclipse.gmf.runtime.notation.Connector;
import org.eclipse.gmf.runtime.notation.IntValueStyle;
import org.eclipse.gmf.runtime.notation.NotationPackage;
import org.eclipse.papyrus.infra.gmfdiag.common.editpolicies.PapyrusConnectionEndEditPolicy;
import org.eclipse.papyrus.uml.diagram.common.editparts.UMLConnectionNodeEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.DurationConstraintLinkEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.figures.DurationLinkFigure;
import org.eclipse.papyrus.uml.diagram.sequence.figures.DurationLinkFigure.Orientation;
import org.eclipse.papyrus.uml.diagram.sequence.locator.IntersectionPointSelectionLocator;
import org.eclipse.papyrus.uml.diagram.sequence.requests.MoveArrowRequest;
import org.eclipse.swt.graphics.Cursor;

/**
 * Edit policy for the selection handles of a {@link DurationConstraintLinkEditPart}
 */
public class DurationLinkSelectionHandlesEditPolicy extends PapyrusConnectionEndEditPolicy implements PropertyChangeListener {
	private UMLConnectionNodeEditPart durationLinkEditPart;
	private TransactionalEditingDomain editingDomain;

	public DurationLinkSelectionHandlesEditPolicy(UMLConnectionNodeEditPart durationLinkEditPart, TransactionalEditingDomain editingDomain) {
		this.durationLinkEditPart = durationLinkEditPart;
		this.editingDomain = editingDomain;
	}

	@Override
	public void setHost(EditPart host) {
		super.setHost(host);
		if (getHost() != null) {
			getHostFigure().addPropertyChangeListener(Connection.PROPERTY_POINTS, this);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	protected List<?> createSelectionHandles() {
		List<Handle> handles = new ArrayList<>();
		handles.addAll((Collection<? extends Handle>) super.createSelectionHandles());
		addSelectionHandles(handles);
		addMoveHandles(handles);
		return handles;
	}

	private void addMoveHandles(List<Handle> list) {
		// middle of the arrow line
		DurationLinkFigure figure = ((DurationLinkFigure) getHostFigure());
		Cursor cursor = getCursor(figure);
		Handle moveHandle = new SquareHandle((ConnectionEditPart) getHost(), new CustomMoveHandleLocator(figure), cursor) {
			@Override
			protected DragTracker createDragTracker() {
				return new ArrowLineMoveTracker();
			}
		};

		list.add(moveHandle);
	}

	private Cursor getCursor(DurationLinkFigure figure) {
		if (figure.getArrowOrientation() == Orientation.VERTICAL) {
			return Cursors.SIZEWE;
		}
		return Cursors.SIZENS;
	}

	private void addSelectionHandles(List<Handle> list) {
		DurationLinkFigure figure = ((DurationLinkFigure) getHostFigure());

		PointList arrowLinePoints = figure.getArrowLinePoints();
		PointList startLinePoints = figure.getStartLinePoints();
		PointList endLinePoints = figure.getEndLinePoints();
		// intersection between start and arrow line
		list.add(new DurationConstraintArrowSelectionHandle(true, durationLinkEditPart, figure, startLinePoints, arrowLinePoints));
		// intersection between end and arrow line
		list.add(new DurationConstraintArrowSelectionHandle(true, durationLinkEditPart, figure, endLinePoints, arrowLinePoints));
	}

	protected SelectEditPartTracker getSelectTracker() {
		return new SelectEditPartTracker(getHost());
	}

	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		// refresh selection handles when the points property changes
		if (getHost().getSelected() != EditPart.SELECTED_NONE) {
			addSelectionHandles();
		}
	}

	class CustomMoveHandleLocator extends ConnectionLocator {

		/**
		 * Constructor.
		 *
		 * @param connection
		 */
		public CustomMoveHandleLocator(Connection connection) {
			super(connection);
		}

		@Override
		protected Point getLocation(PointList points) {
			DurationLinkFigure figure = (DurationLinkFigure) getConnection();
			PointList arrowLinePoints = figure.getArrowLinePoints();
			return arrowLinePoints.getMidpoint();
		}

	}

	class DurationConstraintArrowSelectionHandle extends ConnectionHandle {

		DurationConstraintArrowSelectionHandle(boolean fixed, org.eclipse.gef.GraphicalEditPart owner, Connection connection, PointList pointList1, PointList pointList2) {
			super(fixed);
			setOwner(owner);
			setLocator(new IntersectionPointSelectionLocator(connection, pointList1, pointList2));
		}

		@Override
		protected DragTracker createDragTracker() {
			return new SimpleDragTracker() {
				@Override
				protected String getCommandName() {
					return RequestConstants.REQ_SELECTION;
				}
			};
		}
	}

	class ArrowLineMoveTracker extends SimpleDragTracker {

		@Override
		protected String getCommandName() {
			return MoveArrowRequest.REQ_MOVE_ARROW;
		}

		@Override
		protected void updateSourceRequest() {
			super.updateSourceRequest();
			MoveArrowRequest request = (MoveArrowRequest) getSourceRequest();
			DurationLinkFigure figure = (DurationLinkFigure) durationLinkEditPart.getPrimaryShape();
			request.setArrowOrientation(figure.getArrowOrientation());
			Point location = new Point(getLocation());
			request.setLocation(location);
			Dimension dragMoveDelta = getDragMoveDelta();
			Point moveDelta = new Point(0, 0);
			moveDelta.y += dragMoveDelta.height;
			moveDelta.x += dragMoveDelta.width;
			request.setMoveDelta(moveDelta);
		}

		@Override
		protected Request createSourceRequest() {
			return new MoveArrowRequest();
		}

		@Override
		protected Command getCommand() {
			Request request = getSourceRequest();

			if (request instanceof MoveArrowRequest) {
				ICommand moveArrowCommand = new AbstractTransactionalCommand(editingDomain, "Move arrow", null) {

					@Override
					protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
						Connector connector = (Connector) durationLinkEditPart.getNotationView();

						@SuppressWarnings("unchecked")
						Optional<IntValueStyle> deltaOptional = connector.getStyles().stream().filter(IntValueStyle.class::isInstance).filter(style -> "delta".equals(((IntValueStyle) style).getName())).findFirst();
						IntValueStyle deltaStyle = deltaOptional.orElseGet(() -> {
							IntValueStyle style = (IntValueStyle) connector.createStyle(NotationPackage.eINSTANCE.getIntValueStyle());
							style.setName("delta");
							return style;
						});
						Point moveDelta = ((MoveArrowRequest) request).getMoveDelta();
						Orientation arrowOrientation = ((MoveArrowRequest) request).getArrowOrientation();
						if (arrowOrientation == Orientation.VERTICAL) {
							deltaStyle.setIntValue(deltaStyle.getIntValue() + moveDelta.x);
						} else {
							// horizontal
							deltaStyle.setIntValue(deltaStyle.getIntValue() + moveDelta.y);
						}
						return CommandResult.newOKCommandResult();
					}
				};
				return new ICommandProxy(moveArrowCommand);
			}
			return super.getCommand();
		}

	}

}

Back to the top