Skip to main content
summaryrefslogblamecommitdiffstats
blob: 818c7b59cdc99b5f5631f079cd8d6d4f32c6355e (plain) (tree)


































                                                                                         

                                                                















                                                                                                     

                                                                                    






                                                             
                                                               







                                                                           
                                                                                    
                 
                                                       






                                                        
                                                                                    










                                                                                                                 
                                                             

















                                                                                                      
                                                           



































                                                                                                                                                                                 
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<View> getModelChildren(View lifeline) {
		if (lifeline == null) {
			return Collections.emptyList();
		}
		@SuppressWarnings("unchecked")
		List<View> children = new ArrayList<View>(lifeline.getVisibleChildren());
		List<View> result = sortChildren(children);
		return result;
	}

	private static List<View> sortChildren(List<View> children) {
		List<View> result = new ArrayList<>();
		List<View> original = new ArrayList<>(children);
		for (Iterator<View> 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<View> doSortExecutionSpecifications(List<View> executionSpecifications) {
		if (executionSpecifications.isEmpty()) {
			return executionSpecifications;
		}
		List<View> views = new ArrayList<>(executionSpecifications);
		List<View> 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<View> firstLevelViews = new ArrayList<>();
		for (View view : views) {
			Rectangle rect = getViewBounds(view);
			if (rect.x >= minX - 2 && rect.x <= minX + 2) {
				firstLevelViews.add(view);
			}
		}
		List<View> insertViews = doSortVertically(firstLevelViews);
		for (View view : insertViews) {
			doInsert(view, result, views, new ArrayList<>(insertViews));
		}
		List<View> 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<View> result, List<View> allViews, List<View> ignoreViews) {
		Rectangle r1 = getViewBounds(view);
		r1.width = 16;
		if (!result.contains(view)) {
			result.add(view);
		}
		ignoreViews.add(view);
		List<View> 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<View> doSortVertically(List<View> views) {
		List<View> 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());
	}
}

Back to the top