Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: 5f259f930029cf8fc22bb059fafd2df4f8eb9e19 (plain) (tree)
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
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671







































                                                                     
















                                                                                      



                                                        
                                                                    
                                                                        
                                                                           
                                                                                    



                                                                                                               

























































































































































































































































































































































































































































































































































































































                                                                                                                                                                                                                                                               
                                                                                   
















































                                                                                                                                                     
                                                                                                                 






                                                                                                                                                                                                   
                                                                                                         





















                                                                                                                                      
                                                                               


















                                                                                                                                                      





                                                                              
                                                                               






















































































































































































                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                           















                                                                                                                                                                                                                                          
                                                                                                                                                                                              












                                                                                                                                                      
                                                                                                                                                                                                                                                                      

































                                                                                                                                                    
                                                                                                                                                                                                               













                                                                                                                                                                     
                                            



















































                                                                                                                                                                                                                             
                                                              

                                                                                                                       

                                                                                 











































































































                                                                                                                                                                                                                                  
                                                                                                     










































                                                                                                                                                                        
                                                                                 












                                                                                                                      
                                                                                                                         










                                                                                                                                         
                                                                           































                                                                                           













                                                                                                      
                                                                      









                                                         
                                                         






                                                             
                                                                                   
 
                                                                       
 
                                                                        
































































































                                                                                                                    
                                                                                  









































                                                                                                                           
                  



















                                                                                                                                                                                                          
                                                                                          






















































                                                                                                                          
                                                                                                                                         


















































                                                                                                                                                                                            
                                                   






                                                                                                                                                        

                                                   












                                                                                                                                                        
package org.eclipse.papyrus.uml.diagram.sequence.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

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.ConnectionAnchor;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PrecisionPoint;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.common.command.AbstractCommand;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gef.requests.ChangeBoundsRequest;
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.common.core.command.ICompositeCommand;
import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionNodeEditPart;
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.editparts.ShapeNodeEditPart;
import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest.ViewDescriptor;
import org.eclipse.gmf.runtime.draw2d.ui.figures.BaseSlidableAnchor;
import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter;
import org.eclipse.gmf.runtime.emf.type.core.IHintedType;
import org.eclipse.gmf.runtime.emf.type.core.commands.SetValueCommand;
import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest;
import org.eclipse.gmf.runtime.notation.Anchor;
import org.eclipse.gmf.runtime.notation.Bounds;
import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.IdentityAnchor;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.NotationPackage;
import org.eclipse.gmf.runtime.notation.Shape;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.commands.wrappers.GEFtoEMFCommandWrapper;
import org.eclipse.papyrus.infra.emf.gmf.command.EMFtoGMFCommandWrapper;
import org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramEditPartsUtil;
import org.eclipse.papyrus.uml.diagram.sequence.command.SetResizeAndLocationCommand;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.AbstractExecutionSpecificationEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.AbstractMessageEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.CombinedFragmentCombinedFragmentCompartmentEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.CombinedFragmentEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.InteractionInteractionCompartmentEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.InteractionOperandEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.LifelineEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.policies.OLDLifelineXYLayoutEditPolicy;
import org.eclipse.papyrus.uml.diagram.sequence.part.UMLVisualIDRegistry;
import org.eclipse.papyrus.uml.diagram.sequence.providers.UMLElementTypes;
import org.eclipse.uml2.common.util.CacheAdapter;
import org.eclipse.uml2.uml.CombinedFragment;
import org.eclipse.uml2.uml.ExecutionOccurrenceSpecification;
import org.eclipse.uml2.uml.ExecutionSpecification;
import org.eclipse.uml2.uml.InteractionFragment;
import org.eclipse.uml2.uml.InteractionOperand;
import org.eclipse.uml2.uml.Lifeline;
import org.eclipse.uml2.uml.Message;
import org.eclipse.uml2.uml.MessageOccurrenceSpecification;

public class OperandBoundsComputeHelper {

	/**
	 * Default height of Interaction Operand
	 */
	public static final int DEFAULT_INTERACTION_OPERAND_HEIGHT = 61;

	public static final int MIN_INTERACTION_OPERAND_HEIGHT = 10;

	/**
	 * Default width of Interaction Operand
	 */
	public static final int DEFAULT_INTERACTION_OPERAND_WIDTH = 210;

	/**
	 * Border width of CombinedFragmentFigure
	 */
	public static final int COMBINED_FRAGMENT_FIGURE_BORDER = 1;

	private static final int EXECUTION_VERTICAL_MARGIN = 3;

	/**
	 * Find first Interaction Operand EditpPart of CombinedFragmentCombinedFragmentCompartmentEditPart
	 *
	 * @param compartEP
	 * @return InteractionOperandEditPart
	 */
	public static InteractionOperandEditPart findFirstIOEP(CombinedFragmentCombinedFragmentCompartmentEditPart compartEP) {
		InteractionOperandEditPart firstIOEP = null;
		List<?> children = compartEP.getChildren();
		for (int i = 0; i < children.size(); i++) {
			if (children.get(i) instanceof InteractionOperandEditPart) {
				firstIOEP = (InteractionOperandEditPart) children.get(i);
				break;
			}
		}
		return firstIOEP;
	}

	/**
	 * Find Last Interaction Operand EditpPart of CombinedFragmentCombinedFragmentCompartmentEditPart
	 *
	 * @param compartEP
	 * @return InteractionOperandEditPart
	 */
	public static InteractionOperandEditPart findLastIOEP(CombinedFragmentCombinedFragmentCompartmentEditPart compartEP) {
		InteractionOperandEditPart lastIOEP = null;
		List<?> children = compartEP.getChildren();
		for (int i = children.size() - 1; i >= 0; i--) {
			if (children.get(i) instanceof InteractionOperandEditPart) {
				lastIOEP = (InteractionOperandEditPart) children.get(i);
				break;
			}
		}
		return lastIOEP;
	}

	/**
	 * Find Previous Interaction Operand EditpPart of current given InteractionOperandEditPart
	 *
	 * @param compartEP
	 * @param currentIOEP
	 * @return InteractionOperandEditPart
	 */
	public static InteractionOperandEditPart findPreviousIOEP(CombinedFragmentCombinedFragmentCompartmentEditPart compartEP, InteractionOperandEditPart currentIOEP) {
		InteractionOperandEditPart previousIOEP = null;
		List<?> children = compartEP.getChildren();
		for (int i = 0; i < children.size() - 1; i++) {
			if (children.get(i) instanceof InteractionOperandEditPart) {
				if (children.get(i) == currentIOEP) {
					break;
				} else {
					previousIOEP = (InteractionOperandEditPart) children.get(i);
				}
			}
		}
		return previousIOEP;
	}

	/**
	 * Find Latter Interaction Operand EditpPart of current given InteractionOperandEditPart
	 *
	 * @param compartEP
	 * @param currentIOEP
	 * @return InteractionOperandEditPart
	 */
	public static InteractionOperandEditPart findLatterIOEP(CombinedFragmentCombinedFragmentCompartmentEditPart compartEP, InteractionOperandEditPart currentIOEP) {
		InteractionOperandEditPart latterIOEP = null;
		List<?> children = compartEP.getChildren();
		for (int i = children.size() - 1; i > 0; i--) {
			if (children.get(i) instanceof InteractionOperandEditPart) {
				if (children.get(i) == currentIOEP) {
					break;
				} else {
					latterIOEP = (InteractionOperandEditPart) children.get(i);
				}
			}
		}
		return latterIOEP;
	}

	/**
	 * Update EditPart bounds using new rect
	 *
	 * @param parent
	 * @param rect
	 */
	public static void updateEditPartBounds(GraphicalEditPart editpart, final Rectangle rect) {
		if (editpart.getModel() instanceof Node) {
			Node node = (Node) editpart.getModel();
			if (node.getLayoutConstraint() instanceof Bounds) {
				Bounds bounds = (Bounds) node.getLayoutConstraint();
				updateBounds(bounds, rect, editpart.getEditingDomain());
			}
		}
	}

	/**
	 * Update EditPart bounds using new rect
	 *
	 * @param parent
	 * @param rect
	 */
	public static ICommand createUpdateEditPartBoundsCommand(final GraphicalEditPart editpart, final Rectangle rect) {
		ICommand cmd = new AbstractTransactionalCommand(editpart.getEditingDomain(), "Update Operand Bounds", null) {

			@Override
			protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
				if (editpart.getModel() instanceof Node) {
					Node node = (Node) editpart.getModel();
					if (node.getLayoutConstraint() instanceof Bounds) {
						Bounds bounds = (Bounds) node.getLayoutConstraint();
						fillBounds(bounds, rect);
					}
				}
				return CommandResult.newOKCommandResult();
			}
		};
		return cmd;
	}

	/**
	 * Create command for updating Interaction Operand EditpPart bounds after the CombinedFragment to be created.
	 *
	 * @param editPart
	 * @param request
	 * @return ICommand
	 */
	public static ICommand createUpdateCFAndIOBoundsForCFCreationCommand(final EditPart editPart, final CreateViewRequest request) {
		if (!(editPart instanceof GraphicalEditPart)) {
			return null;
		}
		GraphicalEditPart graphicalEditPart = (GraphicalEditPart) editPart;
		ICommand cmd = new AbstractTransactionalCommand(graphicalEditPart.getEditingDomain(), "Create update operand bounds command", null) {

			@Override
			protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
				OperandBoundsComputeHelper.updateCFAndIOBoundsForCFCreation((GraphicalEditPart) editPart, request);
				return CommandResult.newOKCommandResult();
			}
		};
		return cmd;
	}

	/**
	 * Update Interaction Operand EditpPart bounds after the CombinedFragment to be created.
	 *
	 * @param parent
	 * @param request
	 * @param selectionRect
	 */
	private static void updateCFAndIOBoundsForCFCreation(GraphicalEditPart parent, CreateViewRequest request) {
		Object subEditPart = null;
		if (parent instanceof InteractionInteractionCompartmentEditPart) {
			InteractionInteractionCompartmentEditPart interactionInteractionCompartmentEditPart = (InteractionInteractionCompartmentEditPart) parent;
			subEditPart = interactionInteractionCompartmentEditPart.getChildren().get(interactionInteractionCompartmentEditPart.getChildren().size() - 1);
		} else if (parent instanceof InteractionOperandEditPart) {
			InteractionOperandEditPart interactionOperandEditPart = (InteractionOperandEditPart) parent;
			subEditPart = interactionOperandEditPart.getChildren().get(interactionOperandEditPart.getChildren().size() - 1);
		}
		if (subEditPart != null && subEditPart instanceof CombinedFragmentEditPart) {
			CombinedFragmentEditPart combinedFragmentEditPart = (CombinedFragmentEditPart) subEditPart;
			// set bounds for CombinedFragmentEditPart
			Rectangle cfEPAbsoluteRect = null;
			int labelContainerHeight = computeCombinedFragementHeaderHeight(combinedFragmentEditPart);
			Shape cfEPShape = (Shape) combinedFragmentEditPart.getModel();
			if (cfEPShape.getLayoutConstraint() instanceof Bounds) {
				if (request.getSize() == null) {
					Dimension cfEPDefaultSize = new Dimension();
					cfEPDefaultSize.setWidth(DEFAULT_INTERACTION_OPERAND_WIDTH + COMBINED_FRAGMENT_FIGURE_BORDER * 2);
					cfEPDefaultSize.setHeight(DEFAULT_INTERACTION_OPERAND_HEIGHT + labelContainerHeight + COMBINED_FRAGMENT_FIGURE_BORDER * 2);
					cfEPAbsoluteRect = new Rectangle(request.getLocation(), cfEPDefaultSize);
				} else {
					cfEPAbsoluteRect = new Rectangle(request.getLocation(), request.getSize());
				}
				Rectangle cfEPRelativeRect = cfEPAbsoluteRect.getCopy();
				combinedFragmentEditPart.getFigure().translateToRelative(cfEPRelativeRect);
				Bounds cfEPBounds = (Bounds) cfEPShape.getLayoutConstraint();
				fillBounds(cfEPBounds, cfEPRelativeRect);
			}
			// set bounds for new added Operand
			InteractionOperandEditPart lastOperand = OperandBoundsComputeHelper.findLastIOEP((CombinedFragmentCombinedFragmentCompartmentEditPart) combinedFragmentEditPart.getChildBySemanticHint(UMLVisualIDRegistry
					.getType(CombinedFragmentCombinedFragmentCompartmentEditPart.VISUAL_ID)));
			Shape shape = (Shape) lastOperand.getModel();
			if (shape.getLayoutConstraint() instanceof Bounds) {
				Bounds bounds = (Bounds) shape.getLayoutConstraint();
				Rectangle rect = new Rectangle(bounds.getX(), bounds.getY(), cfEPAbsoluteRect.width() - COMBINED_FRAGMENT_FIGURE_BORDER * 2, cfEPAbsoluteRect.height() - labelContainerHeight - COMBINED_FRAGMENT_FIGURE_BORDER * 2);
				fillBounds(bounds, rect);
			}
		}
	}

	/**
	 * Create command for updating Interaction Operand EditpPart bounds after CombinedFragment to be resized.
	 *
	 * @param compoundCmd
	 * @param request
	 * @param combinedFragmentEditPart
	 * @return Command
	 */
	public static Command createUpdateIOBoundsForCFResizeCommand(CompoundCommand compoundCmd, final ChangeBoundsRequest request, CombinedFragmentEditPart combinedFragmentEditPart) {
		if (combinedFragmentEditPart.getChildren().size() > 0 && combinedFragmentEditPart.getChildren().get(0) instanceof CombinedFragmentCombinedFragmentCompartmentEditPart) {
			CombinedFragmentCombinedFragmentCompartmentEditPart compartment = (CombinedFragmentCombinedFragmentCompartmentEditPart) combinedFragmentEditPart.getChildren().get(0);
			CombinedFragment cf = (CombinedFragment) combinedFragmentEditPart.resolveSemanticElement();
			InteractionOperandEditPart targetIOEP = null;
			if ((request.getResizeDirection() & PositionConstants.NORTH) != 0) {
				targetIOEP = findFirstIOEP(compartment);
			} else if ((request.getResizeDirection() & PositionConstants.SOUTH) != 0) {
				targetIOEP = findLastIOEP(compartment);
			}
			updateIOBoundsForCFResize(request, compoundCmd, compartment.getChildren(), cf, targetIOEP != null ? (InteractionOperand) targetIOEP.resolveSemanticElement() : null, request.getSizeDelta(), request.getResizeDirection());
			if (targetIOEP != null && request.getSizeDelta().height != 0) {
				int heightDelta = request.getSizeDelta().height;
				int movedY = heightDelta;
				Bounds bounds = getInteractionOperandEPBounds(targetIOEP);
				Rectangle currentIOEPRect = OperandBoundsComputeHelper.fillRectangle(bounds);
				if ((request.getResizeDirection() & PositionConstants.NORTH) != 0) {
					movedY = -heightDelta;
					currentIOEPRect.setY(currentIOEPRect.y() - heightDelta);
				} else if ((request.getResizeDirection() & PositionConstants.SOUTH) != 0) {
				}
				currentIOEPRect.setHeight(bounds.getHeight() + heightDelta);
				int minHeight = getMinimumHeightFor(targetIOEP);
				if (currentIOEPRect.height < minHeight) {
					compoundCmd.add(UnexecutableCommand.INSTANCE);
					return UnexecutableCommand.INSTANCE;
				} else {
					Command shiftEnclosedExecutions = getShiftEnclosedFragmentsCommand(targetIOEP, currentIOEPRect, movedY);
					if (shiftEnclosedExecutions != null) {
						compoundCmd.add(shiftEnclosedExecutions);
					}
				}
			}
		}
		// Append command for expand covered Lifelines when moving CombinedFragment.
		Point moveDelta = request.getMoveDelta();
		// Update also happens with resize.
		Dimension sizeDelta = request.getSizeDelta();
		if (moveDelta.y > 0 || sizeDelta.height > 0) {
			if (combinedFragmentEditPart.getModel() instanceof Node) {
				Node node = (Node) combinedFragmentEditPart.getModel();
				if (node.getLayoutConstraint() instanceof Bounds) {
					Bounds containerBounds = (Bounds) node.getLayoutConstraint();
					Dimension preferredSize = combinedFragmentEditPart.getFigure().getPreferredSize();
					int width = containerBounds.getWidth() != -1 ? containerBounds.getWidth() : preferredSize.width();
					int height = containerBounds.getHeight() != -1 ? containerBounds.getHeight() : preferredSize.height();
					int x = containerBounds.getX();
					int y = containerBounds.getY();
					if (moveDelta.y > 0) {
						y += moveDelta.y;
					}
					if (sizeDelta.height > 0) {
						height += sizeDelta.height;
					}
					Rectangle newBounds = new Rectangle(x, y, width, height);
					ICommand command = getExpandCoveredsCommand(combinedFragmentEditPart, newBounds);
					if (command != null && command.canExecute()) {
						compoundCmd.add(new ICommandProxy(command));
					}
				}
			}
		}
		return compoundCmd;
	}

	/**
	 * Update Interaction Operand EditpPart bounds after CombinedFragment to be resized.
	 *
	 * @param request
	 * @param compoundCmd
	 * @param combinedFragmentChildrenEditParts
	 * @param cf
	 * @param targetOperand
	 * @param sizeDelta
	 * @param direction
	 */
	private static void updateIOBoundsForCFResize(final ChangeBoundsRequest request, CompoundCommand compoundCmd, List<EditPart> combinedFragmentChildrenEditParts, CombinedFragment cf, InteractionOperand targetOperand, final Dimension sizeDelta,
			int direction) {
		InteractionOperandEditPart targetOperandEditPart = findTargetOperandEditPart(cf, targetOperand, combinedFragmentChildrenEditParts);
		for (EditPart ep : combinedFragmentChildrenEditParts) {
			if (ep instanceof InteractionOperandEditPart) {
				InteractionOperandEditPart ioEP = (InteractionOperandEditPart) ep;
				Object ioEPModel = ioEP.getModel();
				if (ioEPModel instanceof Shape) {
					Shape ioEPShape = (Shape) ioEPModel;
					Dimension unZoomedSize = sizeDelta.getCopy();
					ioEP.getFigure().translateToRelative(unZoomedSize);
					if (ioEPShape.getLayoutConstraint() instanceof Bounds) {
						final Bounds ioEPOriginalBounds = (Bounds) ioEPShape.getLayoutConstraint();
						ICommand cmd = new UpdateIOBoundsForCFResizeCommand(ioEP.getEditingDomain(), "Update operand bounds interaction command", ioEPOriginalBounds, request, unZoomedSize, ioEP == targetOperandEditPart, direction);
						compoundCmd.add(new ICommandProxy(cmd));
					}
				}
			}
		}
	}

	/**
	 * Update bounds using new rect
	 *
	 * @param bounds
	 * @param rect
	 * @param transactionalEditingDomain
	 */
	public static void updateBounds(final Bounds bounds, final Rectangle rect, TransactionalEditingDomain transactionalEditingDomain) {
		if (bounds != null) {
			final Rectangle originalBounds = new Rectangle();
			originalBounds.setX(bounds.getX());
			originalBounds.setY(bounds.getY());
			originalBounds.setWidth(bounds.getWidth());
			originalBounds.setHeight(bounds.getHeight());
			AbstractCommand cmd = new AbstractCommand() {

				@Override
				public boolean canExecute() {
					return true;
				}

				@Override
				public void execute() {
					exec(rect);
				}

				@Override
				public void redo() {
					execute();
				}

				@Override
				public void undo() {
					exec(originalBounds);
				}

				public void exec(Rectangle rect) {
					fillBounds(bounds, rect);
				}

				@Override
				public boolean canUndo() {
					return true;
				}
			};
			CommandHelper.executeCommandWithoutHistory(transactionalEditingDomain, cmd, true);
		}
	}

	/**
	 * Get InteractionOperandEditPart from its model object InteractionOperand.
	 *
	 * @param cf
	 * @param targetOperand
	 * @param combinedFragmentChildrenEditParts
	 * @return InteractionOperandEditPart
	 */
	public static InteractionOperandEditPart findTargetOperandEditPart(CombinedFragment cf, InteractionOperand targetOperand, List<EditPart> combinedFragmentChildrenEditParts) {
		if (targetOperand == null) {
			return null;
		}
		for (EditPart ep : combinedFragmentChildrenEditParts) {
			if (ep instanceof InteractionOperandEditPart) {
				InteractionOperandEditPart ioEP = (InteractionOperandEditPart) ep;
				EObject io = ioEP.resolveSemanticElement();
				if (cf.getOperands().contains(io)) {
					if (targetOperand.equals(io)) {
						return ioEP;
					}
				}
			}
		}
		return null;
	}

	/**
	 * Get graphical edit part bounds
	 *
	 * @param editPart
	 * @return
	 */
	public static Bounds getEditPartBounds(GraphicalEditPart editPart) {
		if (editPart.getModel() instanceof Node) {
			Node node = (Node) editPart.getModel();
			if (node.getLayoutConstraint() instanceof Bounds) {
				Bounds bounds = (Bounds) node.getLayoutConstraint();
				return bounds;
			}
		}
		return null;
	}

	/**
	 * Fill data from Bounds to Rectangle
	 *
	 * @param source
	 * @return Rectangle
	 */
	public static Rectangle fillRectangle(Bounds source) {
		if (source == null) {
			return null;
		}
		Rectangle target = new Rectangle();
		target.setX(source.getX());
		target.setY(source.getY());
		target.setWidth(source.getWidth());
		target.setHeight(source.getHeight());
		return target;
	}

	/**
	 * Fill data from Rectangle to Bounds
	 *
	 * @param bounds
	 * @param source
	 * @return Bounds
	 */
	public static Bounds fillBounds(Bounds bounds, Rectangle source) {
		if (bounds == null || source == null) {
			return null;
		}
		bounds.setX(source.x());
		bounds.setY(source.y());
		bounds.setWidth(source.width());
		bounds.setHeight(source.height());
		return bounds;
	}

	/**
	 * Get interaction operand bounds
	 *
	 * @param operandEP
	 * @return Bounds
	 */
	public static Bounds getInteractionOperandEPBounds(GraphicalEditPart operandEP) {
		Object lastChildModel = operandEP.getModel();
		if (lastChildModel instanceof Shape) {
			Shape lastOperandShape = (Shape) lastChildModel;
			if (lastOperandShape.getLayoutConstraint() instanceof Bounds) {
				return (Bounds) lastOperandShape.getLayoutConstraint();
			}
		}
		return null;
	}

	/**
	 * Create interaction operand resize command
	 *
	 * @param currentIOEP
	 * @param heightDelta
	 * @param compartEP
	 * @param direction
	 * @return
	 */
	public static Command createIOEPResizeCommand(InteractionOperandEditPart currentIOEP, ChangeBoundsRequest request, CombinedFragmentCombinedFragmentCompartmentEditPart compartEP) {
		int heightDelta = request.getSizeDelta().height();
		int widthDelta = request.getSizeDelta().width();
		int direction = request.getResizeDirection();
		int directionEastWest = request.getResizeDirection() & PositionConstants.EAST_WEST;
		Bounds currentIOEPBounds = OperandBoundsComputeHelper.getEditPartBounds(currentIOEP);
		if (currentIOEPBounds == null) {
			return null;
		}
		InteractionOperandEditPart targetIOEP = null;
		if ((direction & PositionConstants.NORTH) != 0) {
			targetIOEP = OperandBoundsComputeHelper.findPreviousIOEP(compartEP, currentIOEP);
		} else if ((direction & PositionConstants.SOUTH) != 0) {
			targetIOEP = OperandBoundsComputeHelper.findLatterIOEP(compartEP, currentIOEP);
		}
		CompositeCommand compositeCommand = new CompositeCommand("Resize Operand");
		// Resize the CF horizontally
		if (directionEastWest != 0) {
			ChangeBoundsRequest reqEastWest = new ChangeBoundsRequest();
			reqEastWest.setEditParts(currentIOEP);
			reqEastWest.setType(request.getType());
			reqEastWest.setMoveDelta(new Point(request.getMoveDelta().x, 0));
			reqEastWest.setSizeDelta(new Dimension(request.getSizeDelta().width, 0));
			reqEastWest.setLocation(request.getLocation());
			reqEastWest.setExtendedData(request.getExtendedData());
			reqEastWest.setResizeDirection(directionEastWest);
			ICommand horResizeCommand = new CommandProxy(currentIOEP.getParent().getParent().getCommand(reqEastWest));
			compositeCommand.add(horResizeCommand);
		}
		Bounds targetIOEPBounds = OperandBoundsComputeHelper.getEditPartBounds(targetIOEP);
		if (targetIOEPBounds == null) {
			return null;
		}
		if (heightDelta > 0) {
			if (targetIOEPBounds.getHeight() - heightDelta < OperandBoundsComputeHelper.MIN_INTERACTION_OPERAND_HEIGHT) {
				return null;
			}
		} else {
			if (currentIOEPBounds.getHeight() - Math.abs(heightDelta) < OperandBoundsComputeHelper.MIN_INTERACTION_OPERAND_HEIGHT) {
				return null;
			}
		}
		Rectangle targetIOEPRect = OperandBoundsComputeHelper.fillRectangle(targetIOEPBounds);
		Rectangle currentIOEPRect = OperandBoundsComputeHelper.fillRectangle(currentIOEPBounds);
		targetIOEPRect.setHeight(targetIOEPBounds.getHeight() - heightDelta);
		targetIOEPRect.setWidth(targetIOEPBounds.getWidth() + widthDelta);
		currentIOEPRect.setHeight(currentIOEPBounds.getHeight() + heightDelta);
		currentIOEPRect.setWidth(currentIOEPBounds.getWidth() + widthDelta);
		int shiftY = 0;
		if ((direction & PositionConstants.NORTH) != 0) {
			currentIOEPRect.setY(currentIOEPRect.y() - heightDelta);
			shiftY = -heightDelta;
		} else if ((direction & PositionConstants.SOUTH) != 0) {
			targetIOEPRect.setY(targetIOEPRect.y() + heightDelta);
			shiftY = heightDelta;
		}
		int minHeightOfTargetOperand = getMinimumHeightFor(targetIOEP);
		if (targetIOEPRect.height < minHeightOfTargetOperand) {
			return null;
		}
		ICommand previousIOEPCommand = OperandBoundsComputeHelper.createUpdateEditPartBoundsCommand(targetIOEP, targetIOEPRect);
		compositeCommand.add(previousIOEPCommand);
		if ((shiftY < 0 && targetIOEPRect.y < currentIOEPRect.y) || shiftY > 0 && (targetIOEPRect.y > currentIOEPRect.y)) {
			Command shiftPreviousExecutions = getShiftEnclosedFragmentsCommand(targetIOEP, targetIOEPRect, shiftY);
			if (shiftPreviousExecutions != null) {
				compositeCommand.add(new EMFtoGMFCommandWrapper(new GEFtoEMFCommandWrapper(shiftPreviousExecutions)));
			}
		}
		int minHeughtOfCurrentOperand = getMinimumHeightFor(currentIOEP);
		if (currentIOEPRect.height < minHeughtOfCurrentOperand) {
			return null;
		}
		ICommand currentIOEPCommand = OperandBoundsComputeHelper.createUpdateEditPartBoundsCommand(currentIOEP, currentIOEPRect);
		compositeCommand.add(currentIOEPCommand);
		if ((shiftY < 0 && currentIOEPRect.y < targetIOEPRect.y) || (shiftY > 0 && currentIOEPRect.y > targetIOEPRect.y)) {
			Command shiftCurrentExecutions = getShiftEnclosedFragmentsCommand(currentIOEP, currentIOEPRect, shiftY);
			if (shiftCurrentExecutions != null) {
				compositeCommand.add(new EMFtoGMFCommandWrapper(new GEFtoEMFCommandWrapper(shiftCurrentExecutions)));
			}
		}
		return new ICommandProxy(compositeCommand);
	}

	private static int getMinimumHeightFor(InteractionOperandEditPart operand) {
		if (operand == null) {
			return MIN_INTERACTION_OPERAND_HEIGHT;
		}
		List<OperandBlock> operandBlocks = getOperandBlocks(operand);
		if (!operandBlocks.isEmpty()) {
			// 1. Sort with y location.
			Collections.sort(operandBlocks, new Comparator<OperandBlock>() {

				@Override
				public int compare(OperandBlock o1, OperandBlock o2) {
					Rectangle r1 = o1.getBounds();
					Rectangle r2 = o2.getBounds();
					if (r1.y < r2.y) {
						return -1;
					} else if (r1.y > r2.y) {
						return 1;
					}
					return 0;
				}
			});
			// 2. Compute max area of all blocks, make sure all blocks will be contained in this area.
			Rectangle maxArea = null;
			for (OperandBlock blk : operandBlocks) {
				Rectangle r = blk.getBounds();
				if (maxArea == null) {
					maxArea = r;
				} else {
					maxArea.union(r);
				}
			}
			// 3. Compute min area for all blocks, this will remove all margins.
			Map<OperandBlock, Rectangle> constraints = new HashMap<>();
			OperandBlock topBlock = operandBlocks.get(0);
			Rectangle minArea = new Rectangle(topBlock.getBounds());
			minArea.height += EXECUTION_VERTICAL_MARGIN;// margin
			for (int i = 1; i < operandBlocks.size(); i++) {
				OperandBlock nextBlock = operandBlocks.get(i);
				Rectangle r = nextBlock.getBounds();
				if (!minArea.touches(r) && r.y > maxArea.y) {
					for (int y = r.y; y >= maxArea.y; y--) {
						Rectangle movedRect = new Rectangle(r).setY(y);
						if (minArea.touches(movedRect)) {
							break;
						} else {
							constraints.put(nextBlock, movedRect);
						}
					}
				}
				Rectangle newBounds = constraints.get(nextBlock);
				if (newBounds == null) {
					newBounds = r;
				}
				minArea.union(newBounds);
				minArea.height += EXECUTION_VERTICAL_MARGIN;// margin
			}
			return minArea.height;
		}
		return MIN_INTERACTION_OPERAND_HEIGHT;
	}

	/**
	 * Once there are messages between two execution of a Operand, consider them as a group.
	 *
	 * @param currentExecutionPart
	 * @param toCheckExecutions
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	protected static Rectangle getExecutionGroupBounds(IGraphicalEditPart currentExecutionPart, List<ExecutionSpecification> toCheckExecutions) {
		Rectangle groupRect = SequenceUtil.getAbsoluteBounds(currentExecutionPart);
		if (toCheckExecutions.isEmpty()) {
			return groupRect;
		}
		List connections = new ArrayList();
		connections.addAll(currentExecutionPart.getSourceConnections());
		connections.addAll(currentExecutionPart.getTargetConnections());
		for (Object object : connections) {
			IGraphicalEditPart source = (IGraphicalEditPart) object;
			View model = (View) source.getModel();
			EObject element = model.getElement();
			if (toCheckExecutions.contains(element)) {
				List<ExecutionSpecification> myCheckingList = new ArrayList<>(toCheckExecutions);
				myCheckingList.remove(element);
				Rectangle rect = getExecutionGroupBounds(source, myCheckingList);
				groupRect.union(rect);
			}
		}
		List<ShapeNodeEditPart> affixedExecutionSpecificationEditParts = OLDLifelineXYLayoutEditPolicy.getAffixedExecutionSpecificationEditParts((ShapeNodeEditPart) currentExecutionPart);
		for (ShapeNodeEditPart shapeNodeEditPart : affixedExecutionSpecificationEditParts) {
			List<ExecutionSpecification> myCheckingList = new ArrayList<>(toCheckExecutions);
			myCheckingList.remove(shapeNodeEditPart);
			Rectangle rect = getExecutionGroupBounds(shapeNodeEditPart, myCheckingList);
			groupRect.union(rect);
		}
		return groupRect;
	}

	public static Command getShiftEnclosedFragmentsCommand(InteractionOperandEditPart editPart, Rectangle newBounds, int movedY) {
		if (editPart == null || newBounds == null || movedY == 0) {
			return null;
		}
		List<OperandBlock> operandBlocks = getOperandBlocks(editPart);
		if (operandBlocks.isEmpty()) {
			return null;
		}
		OperandBlockLayout layout = new OperandBlockLayout(operandBlocks);
		IFigure figure = editPart.getFigure();
		Rectangle newArea = newBounds.getCopy();
		figure.getParent().translateToAbsolute(newArea);
		newArea.translate(figure.getParent().getBounds().getLocation());
		layout.layout(newArea, movedY > 0 ? true : false);

		final Map<OperandBlock, Integer> blockToMove = new HashMap<>();
		for (OperandBlock blk : operandBlocks) {
			int moveDelta = layout.getMoveDelta(blk);
			if (moveDelta == 0) {
				continue;
			}
			blockToMove.put(blk, moveDelta);
		}
		if (blockToMove.isEmpty()) {
			return null;
		}
		return new ICommandProxy(new MoveOperandBlockCommand(editPart.getEditingDomain(), blockToMove));
	}

	public static Command getForcedShiftEnclosedFragmentsCommand(InteractionOperandEditPart editPart, int movedY, Set<Object> alreadyMovedItems) {
		if (editPart == null || movedY == 0) {
			return null;
		}
		// Recursively process children
		CompoundCommand cc = new CompoundCommand("shift inner CFs' exec blocks"); //$NON-NLS-1$

		List<OperandBlock> operandBlocks = getOperandBlocks(editPart);
		if (operandBlocks.isEmpty()) {
			return null;
		}

		final Map<OperandBlock, Integer> blockToMove = new HashMap<>();
		for (OperandBlock blk : operandBlocks) {
			blockToMove.put(blk, movedY);
		}
		if (blockToMove.isEmpty()) {
			return null;
		}
		cc.add(new ICommandProxy(new MoveOperandBlockCommand(editPart.getEditingDomain(), blockToMove, alreadyMovedItems)));
		return cc;
	}

	private static ICommand getMoveAnchorCommand(int yDelta, Rectangle figureBounds, IdentityAnchor gmfAnchor) {
		String oldTerminal = gmfAnchor.getId();
		PrecisionPoint pp = BaseSlidableAnchor.parseTerminalString(oldTerminal);
		int yPos = (int) Math.round(figureBounds.height * pp.preciseY());
		yPos += yDelta;
		pp.setPreciseY((double) yPos / figureBounds.height);
		if (pp.preciseY() > 1.0) {
			pp.setPreciseY(1.0);
		} else if (pp.preciseY() < 0.0) {
			pp.setPreciseY(0.0);
		}
		String newTerminal = (new BaseSlidableAnchor(null, pp)).getTerminal();
		return new SetValueCommand(new SetRequest(gmfAnchor, NotationPackage.Literals.IDENTITY_ANCHOR__ID, newTerminal));
	}

	/**
	 * Compute CombinedFragement's header height
	 *
	 * @param combinedFragmentEditPart
	 * @return int
	 */
	public static int computeCombinedFragementHeaderHeight(CombinedFragmentEditPart combinedFragmentEditPart) {
		int headerHeight = 0;
		IFigure labelContainer = combinedFragmentEditPart.getPrimaryShape().getHeaderContainer();
		if (labelContainer != null) {
			headerHeight = labelContainer.getPreferredSize().height();
		}
		return headerHeight;
	}

	/**
	 * Check if operation resizing on CombinedFragment is allowed:
	 * Height of its operands must be at least of OperandBoundsComputeHelper.MIN_INTERACTION_OPERAND_HEIGHT
	 * after the resize
	 *
	 * @param request
	 * @param child
	 * @return boolean
	 */
	public static boolean checkRedistrictOnCFResize(ChangeBoundsRequest request, EditPart child) {
		if (child instanceof CombinedFragmentEditPart) {
			if ((request.getResizeDirection() & PositionConstants.NORTH_SOUTH) != 0) {
				CombinedFragmentEditPart combinedFragmentEditPart = (CombinedFragmentEditPart) child;
				if (combinedFragmentEditPart.getChildren().size() > 0 && combinedFragmentEditPart.getChildren().get(0) instanceof CombinedFragmentCombinedFragmentCompartmentEditPart) {
					CombinedFragmentCombinedFragmentCompartmentEditPart compartment = (CombinedFragmentCombinedFragmentCompartmentEditPart) combinedFragmentEditPart.getChildren().get(0);
					List<EditPart> combinedFragmentChildrenEditParts = compartment.getChildren();
					CombinedFragment cf = (CombinedFragment) combinedFragmentEditPart.resolveSemanticElement();
					InteractionOperand targetOperand = null;
					if ((request.getResizeDirection() & PositionConstants.NORTH) != 0) {
						targetOperand = cf.getOperands().get(0);
					} else if ((request.getResizeDirection() & PositionConstants.SOUTH) != 0) {
						targetOperand = cf.getOperands().get(cf.getOperands().size() - 1);
					}
					InteractionOperandEditPart targetOperandEditPart = OperandBoundsComputeHelper.findTargetOperandEditPart(cf, targetOperand, combinedFragmentChildrenEditParts);
					int heightDelta = request.getSizeDelta().height();
					if (targetOperandEditPart != null && heightDelta < 0) {
						int height = targetOperandEditPart.getFigure().getBounds().height();
						if (height - Math.abs(heightDelta) < OperandBoundsComputeHelper.MIN_INTERACTION_OPERAND_HEIGHT) {
							return false;
						}
					}
				}
			}
		}
		return true;
	}

	/**
	 * Add command for updating adjacent interaction operand bounds after deleting a interaction operand
	 *
	 * @param editPart
	 * @param cmd
	 */
	public static void addUpdateBoundsCommandForOperandDelelete(EditPart editPart, ICompositeCommand cmd) {
		if (editPart instanceof InteractionOperandEditPart) {
			if (editPart.getParent() instanceof CombinedFragmentCombinedFragmentCompartmentEditPart) {
				CombinedFragmentCombinedFragmentCompartmentEditPart compartment = (CombinedFragmentCombinedFragmentCompartmentEditPart) editPart.getParent();
				if (compartment.getParent() instanceof CombinedFragmentEditPart) {
					List<EditPart> combinedFragmentChildrenEditParts = compartment.getChildren();
					InteractionOperandEditPart previousIOEP = null;
					InteractionOperandEditPart latterIOEP = null;
					boolean isFirstOperand = false;
					InteractionOperandEditPart currentioEP = (InteractionOperandEditPart) editPart;
					final Rectangle currentioEPBounds = currentioEP.getFigure().getBounds();
					for (int i = 0; i < combinedFragmentChildrenEditParts.size(); i++) {
						EditPart ep = combinedFragmentChildrenEditParts.get(i);
						if (ep instanceof InteractionOperandEditPart) {
							InteractionOperandEditPart ioEP = (InteractionOperandEditPart) ep;
							if (currentioEP == ioEP) {
								if (previousIOEP != null) {
									Object previousIOEPModel = previousIOEP.getModel();
									if (previousIOEPModel instanceof Shape) {
										Shape previousIOEPShape = (Shape) previousIOEPModel;
										if (previousIOEPShape.getLayoutConstraint() instanceof Bounds) {
											final Bounds previousIOEPOriginalBounds = (Bounds) previousIOEPShape.getLayoutConstraint();
											ICommand command = new AbstractTransactionalCommand(previousIOEP.getEditingDomain(), "Merge operand bounds command", null) {

												@Override
												protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
													previousIOEPOriginalBounds.setHeight(previousIOEPOriginalBounds.getHeight() + currentioEPBounds.height());
													return CommandResult.newOKCommandResult();
												}
											};
											cmd.add(command);
										}
									}
									break;
								} else {
									isFirstOperand = true;
									continue;
								}
							} else {
								previousIOEP = ioEP;
							}
							if (isFirstOperand) {
								latterIOEP = ioEP;
								break;
							}
						}
					}
					if (isFirstOperand && latterIOEP != null) {
						Object latterIOEPModel = latterIOEP.getModel();
						if (latterIOEPModel instanceof Shape) {
							Shape latterIOEPShape = (Shape) latterIOEPModel;
							if (latterIOEPShape.getLayoutConstraint() instanceof Bounds) {
								final Bounds latterIOEPOriginalBounds = (Bounds) latterIOEPShape.getLayoutConstraint();
								ICommand command = new AbstractTransactionalCommand(previousIOEP.getEditingDomain(), "Merge operand bounds command", null) {

									@Override
									protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
										latterIOEPOriginalBounds.setY(0);
										latterIOEPOriginalBounds.setHeight(latterIOEPOriginalBounds.getHeight() + currentioEPBounds.height());
										return CommandResult.newOKCommandResult();
									}
								};
								cmd.add(command);
							}
						}
					}
				}
			}
		}
	}

	/**
	 * Add update InteractionOperand bounds command after IO is created
	 *
	 * @param compartment
	 * @param request
	 * @param command
	 */
	public static void addUpdateBoundsForIOCreationCommand(CombinedFragmentCombinedFragmentCompartmentEditPart compartment, ViewDescriptor viewDescriptor, CompositeCommand command) {
		List<?> children = compartment.getChildren();
		if (children != null && children.size() > 0) {
			InteractionOperandEditPart lastOperandEP = OperandBoundsComputeHelper.findLastIOEP(compartment);
			// update bounds
			if (lastOperandEP != null) {
				Bounds lastOperandBounds = OperandBoundsComputeHelper.getInteractionOperandEPBounds(lastOperandEP);
				if (lastOperandBounds != null) {
					Rectangle rect = new Rectangle(lastOperandBounds.getX(), lastOperandBounds.getY() + lastOperandBounds.getHeight(), lastOperandBounds.getWidth(), OperandBoundsComputeHelper.DEFAULT_INTERACTION_OPERAND_HEIGHT);
					// auto update CombinedFragmentEditPart bounds after added new operand
					if (compartment.getParent() instanceof CombinedFragmentEditPart) {
						CombinedFragmentEditPart parent = (CombinedFragmentEditPart) compartment.getParent();
						if (parent.getModel() instanceof Node) {
							Node node = (Node) parent.getModel();
							if (node.getLayoutConstraint() instanceof Bounds) {
								Bounds containerBounds = (Bounds) node.getLayoutConstraint();
								Dimension preferredSize = parent.getFigure().getPreferredSize();
								int width = containerBounds.getWidth() != -1 ? containerBounds.getWidth() : preferredSize.width();
								int height = containerBounds.getHeight() != -1 ? containerBounds.getHeight() : preferredSize.height();
								height = height + OperandBoundsComputeHelper.DEFAULT_INTERACTION_OPERAND_HEIGHT;
								View shapeView = (View) parent.getModel();
								Rectangle newBounds = new Rectangle(containerBounds.getX(), containerBounds.getY(), width, height);
								ICommand setParentBoundsCmd = new SetResizeAndLocationCommand(compartment.getEditingDomain(), DiagramUIMessages.SetLocationCommand_Label_Resize, new EObjectAdapter(shapeView), newBounds);
								command.add(setParentBoundsCmd);
								// Preserve Message anchors.
								ICommand preserveMessageAnchorsCommand = MessageAnchorRepairer.createPreserveMessageAnchorsCommand(parent, OperandBoundsComputeHelper.DEFAULT_INTERACTION_OPERAND_HEIGHT);
								if (preserveMessageAnchorsCommand != null && preserveMessageAnchorsCommand.canExecute()) {
									command.add(preserveMessageAnchorsCommand);
								}
								CombinedFragment combinedFragment = (CombinedFragment) parent.resolveSemanticElement();
								if (!combinedFragment.getCovereds().isEmpty()) {
									ICommand cmd = getExpandCoveredsCommand(parent, newBounds);
									if (cmd != null) {
										command.add(cmd);
									}
								}
							}
						}
					}
					command.add(new SetResizeAndLocationCommand(compartment.getEditingDomain(), DiagramUIMessages.SetLocationCommand_Label_Resize, viewDescriptor, rect));
				}
			}
		} else { // first add operand
			if (compartment.getParent() instanceof CombinedFragmentEditPart) {
				CombinedFragmentEditPart parent = (CombinedFragmentEditPart) compartment.getParent();
				if (parent.getModel() instanceof Node) {
					Node node = (Node) parent.getModel();
					if (node.getLayoutConstraint() instanceof Bounds) {
						Bounds containerBounds = (Bounds) node.getLayoutConstraint();
						Dimension preferredSize = parent.getFigure().getPreferredSize();
						int width = containerBounds.getWidth() != -1 ? containerBounds.getWidth() : preferredSize.width();
						int height = containerBounds.getHeight() != -1 ? containerBounds.getHeight() : preferredSize.height();
						height = height - computeCombinedFragementHeaderHeight(parent);
						command.add(new SetResizeAndLocationCommand(compartment.getEditingDomain(), DiagramUIMessages.SetLocationCommand_Label_Resize, viewDescriptor, new Rectangle(0, 0, width - COMBINED_FRAGMENT_FIGURE_BORDER * 2, height
								- COMBINED_FRAGMENT_FIGURE_BORDER * 2)));
					}
				}
			}
		}
	}

	/**
	 * Expand Lifelines to new Bounds when adding InteractionOperands.
	 *
	 * @param parent
	 * @param newBounds
	 * @return
	 */
	private static ICommand getExpandCoveredsCommand(CombinedFragmentEditPart parent, Rectangle newBounds) {
		CombinedFragment combinedFragment = (CombinedFragment) parent.resolveSemanticElement();
		CompositeCommand command = new CompositeCommand("Expand covered Lifeline by CombinedFragment");
		EList<Lifeline> covereds = combinedFragment.getCovereds();
		for (Lifeline lifeline : covereds) {
			Collection<Setting> settings = CacheAdapter.getInstance().getNonNavigableInverseReferences(lifeline);
			for (Setting ref : settings) {
				if (NotationPackage.eINSTANCE.getView_Element().equals(ref.getEStructuralFeature())) {
					View view = (View) ref.getEObject();
					EditPart part = DiagramEditPartsUtil.getEditPartFromView(view, parent);
					if (view instanceof Node && part instanceof LifelineEditPart) {
						Bounds bounds = (Bounds) ((Node) view).getLayoutConstraint();
						Rectangle rect = new Rectangle(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
						int height = newBounds.bottom() - rect.y;
						if (rect.height == -1) {
							rect.height = ((LifelineEditPart) part).getFigure().getPreferredSize().height;
						}
						if (height > rect.height) {
							int heightDelta = height - rect.height;
							rect.height = height;
							command.add(new SetResizeAndLocationCommand(parent.getEditingDomain(), "Expand covered Lifeline by CombinedFragment", new EObjectAdapter(view), rect));
							command.add(MessageAnchorRepairer.createPreserveMessageAnchorsCommand((LifelineEditPart) part, heightDelta));
						}
						break;
					}
				}
			}
		}
		return command.isEmpty() ? null : command;
	}

	/**
	 * Check if it is a combined fragment.
	 *
	 * @param hint
	 *                 the semantic hint
	 * @return
	 */
	public static boolean isDerivedCombinedFragment(String hint) {
		if (((IHintedType) UMLElementTypes.CombinedFragment_Shape).getSemanticHint().equals(hint)) {
			return true;
		}
		if (((IHintedType) UMLElementTypes.ConsiderIgnoreFragment_Shape).getSemanticHint().equals(hint)) {
			return true;
		}
		return false;
	}

	/**
	 * Command class for updating Interaction Operand EditpPart bounds after CombinedFragment to be resized.
	 *
	 */
	private static final class UpdateIOBoundsForCFResizeCommand extends AbstractTransactionalCommand {

		private final Bounds ioEPOriginalBounds;

		private final ChangeBoundsRequest request;

		private final Dimension sizeDelta;

		private boolean updateHeight = false;

		private int direction;

		private UpdateIOBoundsForCFResizeCommand(TransactionalEditingDomain domain, String label, Bounds ioEPOriginalBounds, ChangeBoundsRequest request, Dimension sizeDelta, boolean updateHeight, int direction) {
			super(domain, label, null);
			this.ioEPOriginalBounds = ioEPOriginalBounds;
			this.request = request;
			this.sizeDelta = sizeDelta;
			this.updateHeight = updateHeight;
			this.direction = direction;
		}

		@Override
		protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
			if (updateHeight) {
				ioEPOriginalBounds.setHeight(ioEPOriginalBounds.getHeight() + sizeDelta.height());
			} else if ((direction & PositionConstants.NORTH) != 0) {
				ioEPOriginalBounds.setY(ioEPOriginalBounds.getY() + sizeDelta.height());
			}
			if ((request.getResizeDirection() & PositionConstants.EAST_WEST) != 0) {
				ioEPOriginalBounds.setWidth(ioEPOriginalBounds.getWidth() + sizeDelta.width());
			}
			return CommandResult.newOKCommandResult();
		}
	}

	private static List<OperandBlock> getOperandBlocks(InteractionOperandEditPart editPart) {
		List<OperandBlock> blocks = new ArrayList<>();
		if (editPart != null) {
			InteractionOperand interactionOperand = (InteractionOperand) editPart.resolveSemanticElement();
			Set<ExecutionSpecification> executions = new HashSet<>();
			Set<Message> messages = new HashSet<>();
			EList<InteractionFragment> fragments = interactionOperand.getFragments();
			for (InteractionFragment fragment : fragments) {
				if (fragment instanceof ExecutionSpecification) {
					executions.add((ExecutionSpecification) fragment);
				} else if (fragment instanceof ExecutionOccurrenceSpecification) {
					ExecutionSpecification execution = ((ExecutionOccurrenceSpecification) fragment).getExecution();
					if (execution != null) {
						executions.add(execution);
					}
				} else if (fragment instanceof MessageOccurrenceSpecification) {
					Message message = ((MessageOccurrenceSpecification) fragment).getMessage();
					if (message != null) {
						messages.add(message);
					}
				}
			}
			final EditPartViewer viewer = editPart.getViewer();
			if (!executions.isEmpty()) {
				for (ExecutionSpecification execution : executions) {
					List<View> existingViews = DiagramEditPartsUtil.findViews(execution, viewer);
					if (existingViews.isEmpty()) {
						continue;
					} else {
						for (View view : existingViews) {
							Object object = viewer.getEditPartRegistry().get(view);
							if (object instanceof ShapeNodeEditPart) {
								ShapeNodeEditPart child = (ShapeNodeEditPart) object;
								boolean visited = false;
								for (OperandBlock blk : blocks) {
									if (blk.contains(child)) {
										visited = true;
										break;
									}
								}
								if (visited) {
									break;
								} else {
									OperandBlock newBlock = new ExecutionOperandBlock(child, executions);
									blocks.add(newBlock);
								}
							}
						}
					}
				}
			}
			if (!messages.isEmpty()) {
				for (Message msg : messages) {
					List<View> existingViews = DiagramEditPartsUtil.findViews(msg, viewer);
					if (existingViews.isEmpty()) {
						continue;
					} else {
						for (View view : existingViews) {
							Object object = viewer.getEditPartRegistry().get(view);
							if (object instanceof ConnectionNodeEditPart) {
								ConnectionNodeEditPart child = (ConnectionNodeEditPart) object;
								EditPart source = child.getSource();
								if (source instanceof AbstractExecutionSpecificationEditPart && executions.contains(((AbstractExecutionSpecificationEditPart) source).resolveSemanticElement())) {
									continue;
								}
								EditPart target = child.getTarget();
								if (target instanceof AbstractExecutionSpecificationEditPart && executions.contains(((AbstractExecutionSpecificationEditPart) target).resolveSemanticElement())) {
									continue;
								}
								boolean visited = false;
								for (OperandBlock blk : blocks) {
									if (blk.contains(child)) {
										visited = true;
										break;
									}
								}
								if (visited) {
									break;
								} else {
									OperandBlock newBlock = new MessageOperandBlock(child);
									blocks.add(newBlock);
								}
							}
						}
					}
				}
			}
		}
		return blocks;
	}

	/**
	 * OperandBlock means the a group with ExecutionSpecifications contained in a InteractionOperand.
	 *
	 * 1. All children of an execution should be contained.
	 * 2. The parent of an execution should be contained.
	 * 3. All ends of connected links which contained in the operand should be contained.
	 *
	 * 4. All children would be moved together.
	 *
	 * @author Jin Liu (jin.liu@soyatec.com)
	 */
	private static class ExecutionOperandBlock extends OperandBlock {


		public ExecutionOperandBlock(ShapeNodeEditPart child, Set<ExecutionSpecification> executions) {
			fillWith(child, executions);
		}

		private void fillWith(ShapeNodeEditPart child, Set<ExecutionSpecification> executions) {
			if (children.contains(child) || child == null || executions == null || executions.isEmpty()) {
				return;
			}
			children.add(child);
			List<ExecutionSpecification> toCheckExecutions = new ArrayList<>(executions);
			toCheckExecutions.remove(child.resolveSemanticElement());
			Set<ShapeNodeEditPart> executionGroups = getExecutionGroups(child, toCheckExecutions);
			if (executionGroups != null && !executionGroups.isEmpty()) {
				for (ShapeNodeEditPart group : executionGroups) {
					fillWith(group, executions);
				}
			}
			LifelineEditPart parent = (LifelineEditPart) child.getParent();
			// 1. parent bar
			List<ShapeNodeEditPart> childShapeNodeEditPart = LifelineEditPartUtil.getChildShapeNodeEditPart(parent);
			childShapeNodeEditPart.remove(child);
			ShapeNodeEditPart parentNode = OLDLifelineXYLayoutEditPolicy.getParent(parent, child.getFigure().getBounds().getCopy(), childShapeNodeEditPart);
			if (parentNode != null) {
				fillWith(parentNode, executions);
			}
			// 2. children
			List<ShapeNodeEditPart> affixedEditParts = OLDLifelineXYLayoutEditPolicy.getAffixedExecutionSpecificationEditParts(child);
			for (ShapeNodeEditPart affixedChild : affixedEditParts) {
				if (executions.contains(affixedChild.resolveSemanticElement())) {
					fillWith(affixedChild, executions);
				}
			}
		}

		@Override
		protected Rectangle computeBounds() {
			Rectangle bounds = null;
			for (EditPart child : children) {
				Rectangle rect = SequenceUtil.getAbsoluteBounds((IGraphicalEditPart) child);
				if (bounds == null) {
					bounds = rect;
				} else {
					bounds.union(rect);
				}
			}
			return bounds;
		}

		@SuppressWarnings({ "unchecked", "rawtypes" })
		private Set<ShapeNodeEditPart> getExecutionGroups(ShapeNodeEditPart executionEditPart, List<ExecutionSpecification> toCheckExecutions) {
			if (toCheckExecutions == null || toCheckExecutions.isEmpty()) {
				return null;
			}
			Set<ShapeNodeEditPart> executionGroups = new HashSet<>();
			List connections = new ArrayList();
			connections.addAll(executionEditPart.getSourceConnections());
			connections.addAll(executionEditPart.getTargetConnections());
			for (Object object : connections) {
				org.eclipse.gef.ConnectionEditPart conn = (org.eclipse.gef.ConnectionEditPart) object;
				IGraphicalEditPart source = (IGraphicalEditPart) conn.getSource();
				if (executionEditPart == conn.getSource()) {
					source = (IGraphicalEditPart) conn.getTarget();
				}
				View model = (View) source.getModel();
				EObject element = model.getElement();
				if (toCheckExecutions.contains(element)) {
					executionGroups.add((ShapeNodeEditPart) source);
					List<ExecutionSpecification> myCheckingList = new ArrayList<>(toCheckExecutions);
					myCheckingList.remove(element);
					Set<ShapeNodeEditPart> myGroups = getExecutionGroups((ShapeNodeEditPart) source, myCheckingList);
					if (myGroups != null) {
						executionGroups.addAll(myGroups);
					}
				}
			}
			return executionGroups;
		}

		public List<ShapeNodeEditPart> getShapeNodeChildren() {
			List<ShapeNodeEditPart> shapes = new ArrayList<>();
			List<EditPart> children = getChildren();
			for (EditPart editPart : children) {
				if (editPart instanceof ShapeNodeEditPart) {
					shapes.add((ShapeNodeEditPart) editPart);
				}
			}
			return shapes;
		}
	}

	private static class MessageOperandBlock extends OperandBlock {


		/**
		 * Constructor.
		 *
		 * @param child
		 * @param messages
		 */
		public MessageOperandBlock(ConnectionNodeEditPart child) {
			children.add(child);
		}

		@Override
		protected Rectangle computeBounds() {
			ConnectionNodeEditPart message = getMessageChild();
			if (message == null) {
				return null;
			}
			Point start = SequenceUtil.getAbsoluteEdgeExtremity(message, true);
			Point end = SequenceUtil.getAbsoluteEdgeExtremity(message, false);
			Rectangle bounds = new Rectangle(start, end);
			if (bounds.height < EXECUTION_VERTICAL_MARGIN) {
				bounds.height = EXECUTION_VERTICAL_MARGIN;
			}
			return bounds;
		}

		public ConnectionNodeEditPart getMessageChild() {
			return (ConnectionNodeEditPart) (children.isEmpty() ? null : children.get(0));
		}

	}

	private static abstract class OperandBlock {

		protected List<EditPart> children = new ArrayList<>();

		public boolean contains(EditPart child) {
			return children.contains(child);
		}

		public Rectangle getBounds() {
			return computeBounds();
		}

		public List<EditPart> getChildren() {
			return new ArrayList<>(children);
		}

		protected abstract Rectangle computeBounds();
	}

	private static class OperandBlockLayout {

		private Map<OperandBlock, Rectangle> constraints = new HashMap<>();

		private List<OperandBlock> fBlocks = new ArrayList<>();

		private List<Rectangle> validBlocks = new ArrayList<>();

		/**
		 * Constructor.
		 *
		 */
		public OperandBlockLayout(List<OperandBlock> blocks) {
			if (blocks != null) {
				for (OperandBlock blk : blocks) {
					if (blk.getBounds() != null) {
						fBlocks.add(blk);
					}
				}
			}
		}

		/**
		 * Sort in y location.
		 */
		private void sortBlocks() {
			Collections.sort(fBlocks, new Comparator<OperandBlock>() {

				@Override
				public int compare(OperandBlock o1, OperandBlock o2) {
					Rectangle r1 = o1.getBounds();
					Rectangle r2 = o2.getBounds();
					if (r1.y < r2.y) {
						return -1;
					} else if (r1.y > r2.y) {
						return 1;
					}
					return 0;
				}
			});
		}

		public void layout(Rectangle newArea, boolean moveDown) {
			constraints.clear();
			validBlocks.clear();
			sortBlocks();
			if (!moveDown) {
				Collections.reverse(fBlocks);
			}
			doLayout(newArea, fBlocks, moveDown);
		}

		public int getMoveDelta(OperandBlock block) {
			Rectangle rect = constraints.get(block);
			if (rect == null) {
				return 0;
			}
			Rectangle bounds = block.getBounds();
			return rect.y - bounds.y;
		}

		private Rectangle getConstraint(OperandBlock blk) {
			Rectangle rect = constraints.get(blk);
			if (rect == null) {
				rect = blk.getBounds();
			}
			return rect;
		}

		private boolean doLayout(Rectangle area, List<OperandBlock> blocks, boolean moveDown) {
			if (blocks.isEmpty()) {
				return false;
			}
			OperandBlock invalidBlock = blocks.get(0);
			if (isValidBlock(area, invalidBlock)) {
				return false;
			}
			if (invalidBlock == null) {
				return false;
			}
			// layout...
			// 1. Near the full area.
			Rectangle rect = invalidBlock.getBounds();
			Rectangle newRect = new Rectangle(rect);
			if (moveDown) {
				int start = rect.y > area.y ? rect.y : area.y;
				for (int y = start; y < area.bottom() - rect.height; y++) {
					newRect.setY(y);
					if (isValidBlock(area, newRect.getExpanded(0, EXECUTION_VERTICAL_MARGIN))) {
						break;
					}
				}
			} else {
				int start = rect.bottom() < area.bottom() ? rect.y : area.bottom() - rect.height;
				for (int y = start; y > area.y; y--) {
					newRect.setY(y);
					if (isValidBlock(area, newRect.getExpanded(0, EXECUTION_VERTICAL_MARGIN))) {
						break;
					}
				}
			}
			constraints.put(invalidBlock, newRect);
			validBlocks.add(newRect);

			List<OperandBlock> remainBlocks = new ArrayList<>(blocks);
			remainBlocks.remove(invalidBlock);
			return doLayout(area, remainBlocks, moveDown);
		}

		private boolean isValidBlock(Rectangle area, OperandBlock blk) {
			Rectangle rect = getConstraint(blk);
			return isValidBlock(area, rect);
		}

		private boolean isValidBlock(Rectangle area, Rectangle block) {
			if (area.y > block.y || area.bottom() < block.bottom()) {
				return false;
			}
			for (Rectangle validRect : validBlocks) {
				if (block.intersects(validRect)) {
					return false;
				}
			}
			return true;
		}

	}

	private static class MoveOperandBlockCommand extends AbstractTransactionalCommand {

		private Map<OperandBlock, Integer> blockToMove;
		private Set<Object> alreadyMovedItems;

		/**
		 * Constructor.
		 *
		 * @param domain
		 * @param label
		 * @param affectedFiles
		 */
		public MoveOperandBlockCommand(TransactionalEditingDomain domain, Map<OperandBlock, Integer> blockToMove) {
			super(domain, "move operand blocks", null);
			this.blockToMove = blockToMove;
		}

		/**
		 * Constructor.
		 *
		 * @param domain
		 * @param label
		 * @param affectedFiles
		 */
		public MoveOperandBlockCommand(TransactionalEditingDomain domain, Map<OperandBlock, Integer> blockToMove, Set<Object> alreadyMovedItems) {
			this(domain, blockToMove);
			this.alreadyMovedItems = alreadyMovedItems;
		}

		/**
		 * @see org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand#doExecuteWithResult(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.core.runtime.IAdaptable)
		 *
		 * @param monitor
		 * @param info
		 * @return
		 * @throws ExecutionException
		 */

		@Override
		protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
			List<OperandBlock> blocks = new ArrayList<>(blockToMove.keySet());
			Collections.sort(blocks, new Comparator<OperandBlock>() {

				@Override
				public int compare(OperandBlock o1, OperandBlock o2) {
					int m1 = Math.abs(blockToMove.get(o1).intValue());
					int m2 = Math.abs(blockToMove.get(o2).intValue());
					if (m1 < m2) {
						return -1;
					} else if (m1 > m2) {
						return 1;
					} else if (m1 == m2) {
						if (m1 > 0) {
							int y1 = o1.getBounds().y;
							int y2 = o2.getBounds().y;
							if (y1 > y2) {
								return -1;
							} else if (y1 < y2) {
								return 1;
							}
						}
					}
					return 0;
				}
			});
			for (int i = 0; i < blocks.size(); i++) {
				OperandBlock block = blocks.get(i);
				int moveDelta = blockToMove.get(block);
				Command command = getMoveOperandBlockCommand(block, moveDelta);
				if (command != null && command.canExecute()) {
					command.execute();
				}
			}
			blockToMove = null;
			return CommandResult.newOKCommandResult();
		}

		private Command getMoveOperandBlockCommand(OperandBlock block, int moveDelta) {
			if (block == null || moveDelta == 0) {
				return null;
			}
			CompoundCommand commands = new CompoundCommand();
			if (block instanceof ExecutionOperandBlock) {
				List<ShapeNodeEditPart> children = ((ExecutionOperandBlock) block).getShapeNodeChildren();
				for (ShapeNodeEditPart child : children) {
					if (alreadyMovedItems != null) {
						if (alreadyMovedItems.contains(child)) {
							continue;
						} else {
							alreadyMovedItems.add(child);
						}
					}
					Bounds bounds = getInteractionOperandEPBounds(child);
					Rectangle newBounds = fillRectangle(bounds);
					newBounds.y += moveDelta;
					CompoundCommand moveCommand = new CompoundCommand();
					ICommand cmd = new SetResizeAndLocationCommand(getEditingDomain(), getLabel(), child, newBounds);
					moveCommand.add(new ICommandProxy(cmd));
					moveCommand = OccurrenceSpecificationMoveHelper.completeMoveExecutionSpecificationCommand(moveCommand, child, newBounds, new ChangeBoundsRequest());
					List<?> targetConnections = child.getTargetConnections();
					for (Object object : targetConnections) {
						if (!(object instanceof AbstractMessageEditPart)) {
							continue;
						}
						AbstractMessageEditPart conn = (AbstractMessageEditPart) object;
						EditPart source = conn.getSource();
						if (!(source instanceof AbstractExecutionSpecificationEditPart)) {
							Edge edge = (Edge) conn.getNotationView();
							Connection connectionFigure = conn.getConnectionFigure();
							ConnectionAnchor sourceAnchor = connectionFigure.getSourceAnchor();
							Rectangle figureBounds = sourceAnchor.getOwner().getBounds();
							Anchor gmfTargetAnchor = edge.getSourceAnchor();
							if (gmfTargetAnchor instanceof IdentityAnchor) {
								ICommand moveAnchorCommand = getMoveAnchorCommand(moveDelta, figureBounds, (IdentityAnchor) gmfTargetAnchor);
								if (moveAnchorCommand != null && moveAnchorCommand.canExecute()) {
									commands.add(new ICommandProxy(moveAnchorCommand));
								}
							}
						}
					}
					List<?> sourceConnections = child.getSourceConnections();
					for (Object object : sourceConnections) {
						if (!(object instanceof AbstractMessageEditPart)) {
							continue;
						}
						AbstractMessageEditPart conn = (AbstractMessageEditPart) object;
						EditPart target = conn.getTarget();
						if (!(target instanceof AbstractExecutionSpecificationEditPart)) {
							Edge edge = (Edge) conn.getNotationView();
							Connection connectionFigure = conn.getConnectionFigure();
							ConnectionAnchor targetAnchor = connectionFigure.getTargetAnchor();
							Rectangle figureBounds = targetAnchor.getOwner().getBounds();
							Anchor gmfTargetAnchor = edge.getTargetAnchor();
							if (gmfTargetAnchor instanceof IdentityAnchor) {
								ICommand moveAnchorCommand = getMoveAnchorCommand(moveDelta, figureBounds, (IdentityAnchor) gmfTargetAnchor);
								if (moveAnchorCommand != null && moveAnchorCommand.canExecute()) {
									commands.add(new ICommandProxy(moveAnchorCommand));
								}
							}
						}
					}
					commands.add(moveCommand);
				}
			} else if (block instanceof MessageOperandBlock) {
				ConnectionNodeEditPart message = ((MessageOperandBlock) block).getMessageChild();
				if (message != null) {
					Edge edge = (Edge) message.getModel();
					Connection msgFigure = message.getConnectionFigure();
					{ // Source
						ConnectionAnchor sourceAnchor = msgFigure.getSourceAnchor();
						IdentityAnchor gmfSourceAnchor = (IdentityAnchor) edge.getSourceAnchor();
						Rectangle figureBounds = sourceAnchor.getOwner().getBounds();
						if (gmfSourceAnchor != null) {
							commands.add(new ICommandProxy(getMoveAnchorCommand(moveDelta, figureBounds, gmfSourceAnchor)));
						}
					}

					{ // Target
						IdentityAnchor gmfTargetAnchor = (IdentityAnchor) edge.getTargetAnchor();
						ConnectionAnchor targetAnchor = msgFigure.getTargetAnchor();
						Rectangle figureBounds = targetAnchor.getOwner().getBounds();
						if (gmfTargetAnchor != null) {
							commands.add(new ICommandProxy(getMoveAnchorCommand(moveDelta, figureBounds, gmfTargetAnchor)));
						}
					}
				}
			}
			return commands.unwrap();
		}
	}
}

Back to the top