package org.eclipse.papyrus.uml.diagram.sequence.util; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil; import org.eclipse.gmf.runtime.notation.NotationPackage; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.uml2.uml.ExecutionSpecification; public class LifelineModelChildrenHelper { /** * Try to fixed the bug about display ExecutionSpecifications(ES). * * At some times, the child ES would be displayed under the parent ES. * * Fixed to sort them with bounds in model before creating. */ public static List getModelChildren(View lifeline) { if (lifeline == null) { return Collections.emptyList(); } @SuppressWarnings("unchecked") List children = new ArrayList(lifeline.getVisibleChildren()); List result = sortChildren(children); return result; } private static List sortChildren(List children) { List result = new ArrayList<>(); List original = new ArrayList<>(children); for (Iterator iterator = original.iterator(); iterator.hasNext();) { View view = iterator.next(); EObject elt = ViewUtil.resolveSemanticElement(view); if (!(elt instanceof ExecutionSpecification)) { result.add(view); iterator.remove(); } } result.addAll(doSortExecutionSpecifications(original)); return result; } private static List doSortExecutionSpecifications(List executionSpecifications) { if (executionSpecifications.isEmpty()) { return executionSpecifications; } List views = new ArrayList<>(executionSpecifications); List result = new ArrayList<>(executionSpecifications.size()); int minX = -1; for (View view : views) { Rectangle rect = getViewBounds(view); if (minX == -1 || rect.x < minX) { minX = rect.x; } } List firstLevelViews = new ArrayList<>(); for (View view : views) { Rectangle rect = getViewBounds(view); if (rect.x >= minX - 2 && rect.x <= minX + 2) { firstLevelViews.add(view); } } List insertViews = doSortVertically(firstLevelViews); for (View view : insertViews) { doInsert(view, result, views, new ArrayList<>(insertViews)); } List remains = new ArrayList<>(); for (View view : views) { if (!result.contains(view)) { remains.add(view); } } insertViews = doSortVertically(remains); for (View view : remains) { doInsert(view, result, views, new ArrayList<>(insertViews)); } return result; } private static void doInsert(View view, List result, List allViews, List ignoreViews) { Rectangle r1 = getViewBounds(view); r1.width = 16; if (!result.contains(view)) { result.add(view); } ignoreViews.add(view); List newLevelViews = new ArrayList<>(); for (View v : allViews) { if (ignoreViews.contains(v)) { continue; } Rectangle r2 = getViewBounds(v); r2.width = 16; if (r2.x > r1.x && r2.x < r1.right() && r2.y >= r1.y && r2.y <= r1.bottom()) { newLevelViews.add(v); } } newLevelViews = doSortVertically(newLevelViews); ignoreViews.addAll(newLevelViews); for (View v : newLevelViews) { doInsert(v, result, allViews, ignoreViews); } } private static List doSortVertically(List views) { List insertViews = new ArrayList<>(); for (int i = 0; i < views.size(); i++) { View current = views.get(i); Rectangle r1 = getViewBounds(current); int index = insertViews.size(); for (int j = 0; j < insertViews.size(); j++) { Rectangle r2 = getViewBounds(insertViews.get(j)); if (r1.y < r2.y) { index = j; } } insertViews.add(index, current); } return insertViews; } private static Rectangle getViewBounds(View view) { if (view == null) { return null; } Integer x = getFeatureValue(view, NotationPackage.eINSTANCE.getLocation_X()); Integer y = getFeatureValue(view, NotationPackage.eINSTANCE.getLocation_Y()); Integer width = getFeatureValue(view, NotationPackage.eINSTANCE.getSize_Width()); Integer height = getFeatureValue(view, NotationPackage.eINSTANCE.getSize_Height()); if (x == null && y == null && width == null && height == null) { return null; } return new Rectangle(x == null ? 0 : x.intValue(), y == null ? 0 : y.intValue(), width == null ? -1 : width.intValue(), height == null ? -1 : height.intValue()); } private static Integer getFeatureValue(View view, EStructuralFeature feature) { if (view == null || feature == null) { return null; } return (Integer) ViewUtil.getPropertyValue(view, feature, feature.getEContainingClass()); } }