Project: BPMN2-Editor-for-Eclipse
/******************************************************************************* 
 * Copyright (c) 2011 Red Hat, Inc.  
 *  All rights reserved.  
 * This program is made available under the terms of the  
 * Eclipse Public License v1.0 which accompanies this distribution,  
 * and is available at http://www.eclipse.org/legal/epl-v10.html  
 *  
 * Contributors:  
 * Red Hat, Inc. - initial API and implementation  
 ******************************************************************************/
package org.eclipse.bpmn2.modeler.core.utils; 
 
import java.awt.Dimension; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.Iterator; 
import java.util.List; 
 
import org.eclipse.bpmn2.BaseElement; 
import org.eclipse.bpmn2.FlowElement; 
import org.eclipse.bpmn2.Lane; 
import org.eclipse.bpmn2.Participant; 
import org.eclipse.bpmn2.SubProcess; 
import org.eclipse.bpmn2.TextAnnotation; 
import org.eclipse.bpmn2.modeler.core.ModelHandler; 
import org.eclipse.bpmn2.modeler.core.ModelHandlerLocator; 
import org.eclipse.bpmn2.modeler.core.di.DIUtils; 
import org.eclipse.bpmn2.modeler.core.features.BusinessObjectUtil; 
import org.eclipse.emf.common.util.ECollections; 
import org.eclipse.emf.common.util.EList; 
import org.eclipse.emf.ecore.EObject; 
import org.eclipse.graphiti.features.context.IPictogramElementContext; 
import org.eclipse.graphiti.features.context.ITargetContext; 
import org.eclipse.graphiti.mm.algorithms.AbstractText; 
import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm; 
import org.eclipse.graphiti.mm.algorithms.Polyline; 
import org.eclipse.graphiti.mm.algorithms.Text; 
import org.eclipse.graphiti.mm.algorithms.styles.Point; 
import org.eclipse.graphiti.mm.pictograms.ContainerShape; 
import org.eclipse.graphiti.mm.pictograms.Diagram; 
import org.eclipse.graphiti.mm.pictograms.PictogramElement; 
import org.eclipse.graphiti.mm.pictograms.Shape; 
import org.eclipse.graphiti.services.Graphiti; 
import org.eclipse.graphiti.services.IGaService; 
import org.eclipse.graphiti.services.IPeService; 
 
public class FeatureSupport { 
 
 public static boolean isTargetSubProcess(ITargetContext context) { 
  return BusinessObjectUtil.containsElementOfType(context.getTargetContainer(), SubProcess.class); 
 
 
 public static boolean isTargetLane(ITargetContext context) { 
  return isLane(context.getTargetContainer()); 
 
 
 public static boolean isLane(PictogramElement element) { 
  return BusinessObjectUtil.containsElementOfType(element, Lane.class); 
 
 
 public static boolean isTargetParticipant(ITargetContext context) { 
  return isParticipant(context.getTargetContainer()); 
 
 
 public static boolean isParticipant(PictogramElement element) { 
  return BusinessObjectUtil.containsElementOfType(element, Participant.class); 
 
 
 public static boolean isLaneOnTop(Lane lane) { 
  return lane.getChildLaneSet() == null || lane.getChildLaneSet().getLanes().isEmpty(); 
 
 
 public static boolean isTargetLaneOnTop(ITargetContext context) { 
  Lane lane = BusinessObjectUtil.getFirstElementOfType(context.getTargetContainer(), Lane.class); 
  return lane.getChildLaneSet() == null || lane.getChildLaneSet().getLanes().isEmpty(); 
 
 
 /**
  * Use ModelHandler.getInstance(diagram) instead 
  *  
  * @param diagram 
  * @return 
  * @throws IOException 
  */
 
 @Deprecated 
 public static ModelHandler getModelHanderInstance(Diagram diagram) throws IOException { 
  return ModelHandlerLocator.getModelHandler(diagram.eResource()); 
 
 
 public static void redraw(ContainerShape container) { 
  ContainerShape root = getRootContainer(container); 
  resizeRecursively(root); 
  postResizeFixLenghts(root); 
  updateDI(root); 
 
 
 private static void updateDI(ContainerShape root) { 
  Diagram diagram = Graphiti.getPeService().getDiagramForPictogramElement(root); 
 
  Class<?> instanceClass = BusinessObjectUtil.getFirstElementOfType(root, BaseElement.class).eClass() 
    .getInstanceClass(); 
  DIUtils.updateDIShape(root); 
 
 
 private static ContainerShape getRootContainer(ContainerShape container) { 
  ContainerShape parent = container.getContainer(); 
  EObject bo = BusinessObjectUtil.getFirstElementOfType(parent, BaseElement.class); 
  if (bo != null && (bo instanceof Lane || bo instanceof Participant)) { 
   return getRootContainer(parent); 
  
  return container; 
 
 
 private static Dimension resize(ContainerShape container) { 
  EObject elem = BusinessObjectUtil.getFirstElementOfType(container, BaseElement.class); 
  IGaService service = Graphiti.getGaService(); 
  int height = 0
  int width = container.getGraphicsAlgorithm().getWidth() - 15
 
  EList<Shape> children = container.getChildren(); 
  ECollections.sort(children, new SiblingLaneComparator()); 
  for (Shape s : children) { 
   Object bo = BusinessObjectUtil.getFirstElementOfType(s, BaseElement.class); 
   if (bo != null && (bo instanceof Lane || bo instanceof Participant) && !bo.equals(elem)) { 
    GraphicsAlgorithm ga = s.getGraphicsAlgorithm(); 
    service.setLocation(ga, 15, height); 
    height += ga.getHeight() - 1
    if (ga.getWidth() >= width) { 
     width = ga.getWidth(); 
    else { 
     service.setSize(ga, width, ga.getHeight()); 
    
   
  
 
  GraphicsAlgorithm ga = container.getGraphicsAlgorithm(); 
 
  if (height == 0) { 
   return new Dimension(ga.getWidth(), ga.getHeight()); 
  else { 
   int newWidth = width + 15
   int newHeight = height + 1
   service.setSize(ga, newWidth, newHeight); 
 
   for (Shape s : children) { 
    GraphicsAlgorithm childGa = s.getGraphicsAlgorithm(); 
    if (childGa instanceof Text) { 
     s.getGraphicsAlgorithm().setHeight(newHeight); 
    else if (childGa instanceof Polyline) { 
     Polyline line = (Polyline) childGa; 
     Point firstPoint = line.getPoints().get(0); 
     Point newPoint = service.createPoint(firstPoint.getX(), newHeight); 
     line.getPoints().set(1, newPoint); 
    
   
 
   return new Dimension(newWidth, newHeight); 
  
 
 
 private static Dimension resizeRecursively(ContainerShape root) { 
  BaseElement elem = BusinessObjectUtil.getFirstElementOfType(root, BaseElement.class); 
  List<Dimension> dimensions = new ArrayList<Dimension>(); 
  IGaService service = Graphiti.getGaService(); 
  int foundContainers = 0
 
  for (Shape s : root.getChildren()) { 
   Object bo = BusinessObjectUtil.getFirstElementOfType(s, BaseElement.class); 
   if (checkForResize(elem, s, bo)) { 
    foundContainers += 1
    Dimension d = resizeRecursively((ContainerShape) s); 
    if (d != null) { 
     dimensions.add(d); 
    
   
  
 
  if (dimensions.isEmpty()) { 
   GraphicsAlgorithm ga = root.getGraphicsAlgorithm(); 
   for (Shape s : root.getChildren()) { 
    GraphicsAlgorithm childGa = s.getGraphicsAlgorithm(); 
    if (childGa instanceof Text) { 
     s.getGraphicsAlgorithm().setHeight(ga.getHeight()); 
    else if (childGa instanceof Polyline) { 
     Polyline line = (Polyline) childGa; 
     Point firstPoint = line.getPoints().get(0); 
     Point newPoint = service.createPoint(firstPoint.getX(), ga.getHeight()); 
     line.getPoints().set(1, newPoint); 
    
   
   return new Dimension(ga.getWidth(), ga.getHeight()); 
  
 
  if (foundContainers > 0) { 
   return resize(root); 
  
 
  return getMaxDimension(dimensions); 
 
 
 /**
  * One can only resize lanes and participants 
  */
 
 private static boolean checkForResize(BaseElement currentBo, Shape s, Object bo) { 
  if (!(s instanceof ContainerShape)) { 
   return false
  
  if (bo == null) { 
   return false
  
  if (!(bo instanceof Lane || bo instanceof Participant)) { 
   return false
  
  return !bo.equals(currentBo); 
 
 
 private static Dimension getMaxDimension(List<Dimension> dimensions) { 
  if (dimensions.isEmpty()) { 
   return null
  
  int height = 0
  int width = 0
 
  for (Dimension d : dimensions) { 
   height += d.height; 
   if (d.width > width) { 
    width = d.width; 
   
  
 
  return new Dimension(width, height); 
 
 
 private static void postResizeFixLenghts(ContainerShape root) { 
  IGaService service = Graphiti.getGaService(); 
  BaseElement elem = BusinessObjectUtil.getFirstElementOfType(root, BaseElement.class); 
  int width = root.getGraphicsAlgorithm().getWidth() - 15
 
  for (Shape s : root.getChildren()) { 
   Object o = BusinessObjectUtil.getFirstElementOfType(s, BaseElement.class); 
   if (checkForResize(elem, s, o)) { 
    GraphicsAlgorithm ga = s.getGraphicsAlgorithm(); 
    service.setSize(ga, width, ga.getHeight()); 
    postResizeFixLenghts((ContainerShape) s); 
   
  
 
 
 public static String getShapeValue(IPictogramElementContext context) { 
  String value = null
 
  PictogramElement pe = context.getPictogramElement(); 
  if (pe instanceof ContainerShape) { 
   ContainerShape cs = (ContainerShape) pe; 
   for (Shape shape : cs.getChildren()) { 
    if (shape.getGraphicsAlgorithm() instanceof AbstractText) { 
     AbstractText text = (AbstractText) shape.getGraphicsAlgorithm(); 
     value = text.getValue(); 
    
   
  
  return value; 
 
 
 public static String getBusinessValue(IPictogramElementContext context) { 
  Object o = BusinessObjectUtil.getFirstElementOfType(context.getPictogramElement(), BaseElement.class); 
  if (o instanceof FlowElement) { 
   FlowElement e = (FlowElement) o; 
   return e.getName(); 
  else if (o instanceof TextAnnotation) { 
   TextAnnotation a = (TextAnnotation) o; 
   return a.getText(); 
  else if (o instanceof Participant) { 
   Participant p = (Participant) o; 
   return p.getName(); 
  else if (o instanceof Lane) { 
   Lane l = (Lane) o; 
   return l.getName(); 
  
  return null
 
 
 public static Participant getTargetParticipant(ITargetContext context, ModelHandler handler) { 
  if (context.getTargetContainer() instanceof Diagram) { 
   return handler.getInternalParticipant(); 
  
 
  Object bo = BusinessObjectUtil.getFirstElementOfType(context.getTargetContainer(), BaseElement.class); 
 
  if (bo instanceof Participant) { 
   return (Participant) bo; 
  
 
  return handler.getParticipant(bo); 
 
 
 public static Shape getShape(ContainerShape container, String property, String expectedValue) { 
  IPeService peService = Graphiti.getPeService(); 
  Iterator<Shape> iterator = peService.getAllContainedShapes(container).iterator(); 
  while (iterator.hasNext()) { 
   Shape shape = iterator.next(); 
   String value = peService.getPropertyValue(shape, property); 
   if (value != null && value.equals(expectedValue)) { 
    return shape; 
   
  
  return null
 
 
 @SuppressWarnings("unchecked"
 public static <T extends EObject> T getChildElementOfType(PictogramElement container, String property, String expectedValue, Class<T> clazz) { 
  IPeService peService = Graphiti.getPeService(); 
  Iterator<PictogramElement> iterator = peService.getAllContainedPictogramElements(container).iterator(); 
  while (iterator.hasNext()) { 
   PictogramElement pe = iterator.next(); 
   String value = peService.getPropertyValue(pe, property); 
   if (value != null && value.equals(expectedValue) && clazz.isInstance(pe)) { 
    return (T) pe; 
   
  
  return null
 
}