Package org.eclipse.bpmn2.modeler.ui.features.flow

Source Code of org.eclipse.bpmn2.modeler.ui.features.flow.SequenceFlowFeatureContainer$SequenceFlowReconnectionFeature

/*******************************************************************************
* 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.ui.features.flow;

import java.util.Iterator;

import org.eclipse.bpmn2.Activity;
import org.eclipse.bpmn2.BaseElement;
import org.eclipse.bpmn2.ComplexGateway;
import org.eclipse.bpmn2.ExclusiveGateway;
import org.eclipse.bpmn2.FlowNode;
import org.eclipse.bpmn2.InclusiveGateway;
import org.eclipse.bpmn2.SequenceFlow;
import org.eclipse.bpmn2.di.BPMNEdge;
import org.eclipse.bpmn2.modeler.core.Activator;
import org.eclipse.bpmn2.modeler.core.ModelHandler;
import org.eclipse.bpmn2.modeler.core.features.BaseElementConnectionFeatureContainer;
import org.eclipse.bpmn2.modeler.core.features.BaseElementReconnectionFeature;
import org.eclipse.bpmn2.modeler.core.features.BusinessObjectUtil;
import org.eclipse.bpmn2.modeler.core.features.MultiUpdateFeature;
import org.eclipse.bpmn2.modeler.core.features.UpdateBaseElementNameFeature;
import org.eclipse.bpmn2.modeler.core.features.flow.AbstractAddFlowFeature;
import org.eclipse.bpmn2.modeler.core.features.flow.AbstractCreateFlowFeature;
import org.eclipse.bpmn2.modeler.core.utils.StyleUtil;
import org.eclipse.bpmn2.modeler.core.utils.Tuple;
import org.eclipse.bpmn2.modeler.ui.ImageProvider;
import org.eclipse.dd.di.DiagramElement;
import org.eclipse.graphiti.features.IAddFeature;
import org.eclipse.graphiti.features.ICreateConnectionFeature;
import org.eclipse.graphiti.features.IDeleteFeature;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.IReason;
import org.eclipse.graphiti.features.IReconnectionFeature;
import org.eclipse.graphiti.features.IUpdateFeature;
import org.eclipse.graphiti.features.context.IAddContext;
import org.eclipse.graphiti.features.context.IReconnectionContext;
import org.eclipse.graphiti.features.context.IUpdateContext;
import org.eclipse.graphiti.features.context.impl.ReconnectionContext;
import org.eclipse.graphiti.features.impl.AbstractUpdateFeature;
import org.eclipse.graphiti.features.impl.Reason;
import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
import org.eclipse.graphiti.mm.algorithms.Polyline;
import org.eclipse.graphiti.mm.algorithms.styles.Color;
import org.eclipse.graphiti.mm.pictograms.Connection;
import org.eclipse.graphiti.mm.pictograms.ConnectionDecorator;
import org.eclipse.graphiti.mm.pictograms.Diagram;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.graphiti.services.IGaService;
import org.eclipse.graphiti.services.IPeService;
import org.eclipse.graphiti.util.IColorConstant;

public class SequenceFlowFeatureContainer extends BaseElementConnectionFeatureContainer {

  private static final String IS_DEFAULT_FLOW_PROPERTY = "is.default.flow";
  private static final String IS_CONDITIONAL_FLOW_PROPERTY = "is.conditional.flow";
  private static final String DEFAULT_MARKER_PROPERTY = "default.marker";
  private static final String CONDITIONAL_MARKER_PROPERTY = "conditional.marker";

  @Override
  public boolean canApplyTo(Object o) {
    return super.canApplyTo(o) && o instanceof SequenceFlow;
  }

  @Override
  public IAddFeature getAddFeature(IFeatureProvider fp) {
    return new AbstractAddFlowFeature(fp) {
      @Override
      protected Class<? extends BaseElement> getBoClass() {
        return SequenceFlow.class;
      }

      @Override
      protected void createConnectionDecorators(Connection connection) {
        int w = 3;
        int l = 8;
       
        ConnectionDecorator decorator = Graphiti.getPeService().createConnectionDecorator(connection, false,
            1.0, true);

        IGaService gaService = Graphiti.getGaService();
        Polyline arrow = gaService.createPolygon(decorator, new int[] { -l, w, 0, 0, -l, -w, -l, w });

        arrow.setForeground(manageColor(StyleUtil.CLASS_FOREGROUND));
        arrow.setLineWidth(2);
      }

      @Override
      protected void hook(IAddContext context, Connection connection, BaseElement element) {
        setDefaultSequenceFlow(connection);
        setConditionalSequenceFlow(connection);
      }
    };
  }

  @Override
  public ICreateConnectionFeature getCreateConnectionFeature(IFeatureProvider fp) {
    return new CreateSequenceFlowFeature(fp);
  }

  @Override
  public IUpdateFeature getUpdateFeature(IFeatureProvider fp) {
    MultiUpdateFeature multiUpdate = new MultiUpdateFeature(fp);
    multiUpdate.addUpdateFeature(new UpdateDefaultSequenceFlowFeature(fp));
    multiUpdate.addUpdateFeature(new UpdateConditionalSequenceFlowFeature(fp));
    multiUpdate.addUpdateFeature(new UpdateBaseElementNameFeature(fp));
    return multiUpdate;
  }

  @Override
  public IReconnectionFeature getReconnectionFeature(IFeatureProvider fp) {
    return new SequenceFlowReconnectionFeature(fp);
  }

  @Override
  public IDeleteFeature getDeleteFeature(IFeatureProvider fp) {
    return null;
  }

  public static class CreateSequenceFlowFeature extends AbstractCreateFlowFeature<FlowNode, FlowNode> {

    public CreateSequenceFlowFeature(IFeatureProvider fp) {
      super(fp, "Sequence Flow",
          "A Sequence Flow is used to show the order that Activities will be performed in a Process");
    }

    @Override
    protected String getStencilImageId() {
      return ImageProvider.IMG_16_SEQUENCE_FLOW;
    }

    @Override
    protected BaseElement createFlow(ModelHandler mh, FlowNode source, FlowNode target) {
      SequenceFlow flow = mh.createSequenceFlow(source, target);
      flow.setName("");
      return flow;
    }

    @Override
    protected Class<FlowNode> getSourceClass() {
      return FlowNode.class;
    }

    @Override
    protected Class<FlowNode> getTargetClass() {
      return FlowNode.class;
    }
  }

  private static Color manageColor(PictogramElement element, IColorConstant colorConstant) {
    IPeService peService = Graphiti.getPeService();
    Diagram diagram = peService.getDiagramForPictogramElement(element);
    return Graphiti.getGaService().manageColor(diagram, colorConstant);
  }
 
  private static void setDefaultSequenceFlow(Connection connection) {
    IPeService peService = Graphiti.getPeService();
    SequenceFlow flow = BusinessObjectUtil.getFirstElementOfType(connection, SequenceFlow.class);
    SequenceFlow defaultFlow = getDefaultFlow(flow.getSourceRef());
    boolean isDefault = defaultFlow == null ? false : defaultFlow.equals(flow);

    Tuple<ConnectionDecorator, ConnectionDecorator> decorators = getConnectionDecorators(connection);
    ConnectionDecorator def = decorators.getFirst();
    ConnectionDecorator cond = decorators.getSecond();

    if (isDefault) {
      if (cond != null) {
        peService.deletePictogramElement(cond);
      }
      def = createDefaultConnectionDecorator(connection);
      GraphicsAlgorithm ga = def.getGraphicsAlgorithm();
      ga.setForeground(manageColor(connection,StyleUtil.CLASS_FOREGROUND));
    } else {
      if (def != null) {
        peService.deletePictogramElement(def);
      }
      if (flow.getConditionExpression() != null && flow.getSourceRef() instanceof Activity) {
        cond = createConditionalConnectionDecorator(connection);
        GraphicsAlgorithm ga = cond.getGraphicsAlgorithm();
        ga.setFilled(true);
        ga.setForeground(manageColor(connection,StyleUtil.CLASS_FOREGROUND));
        ga.setBackground(manageColor(connection,IColorConstant.WHITE));
      }
    }

    peService.setPropertyValue(connection, IS_DEFAULT_FLOW_PROPERTY,
        Boolean.toString(isDefault));

  }
 
  public static class UpdateDefaultSequenceFlowFeature extends AbstractUpdateFeature {

    public UpdateDefaultSequenceFlowFeature(IFeatureProvider fp) {
      super(fp);
    }

    @Override
    public boolean canUpdate(IUpdateContext context) {
      SequenceFlow flow = BusinessObjectUtil.getFirstElementOfType(context.getPictogramElement(),
          SequenceFlow.class);
      boolean canUpdate = flow != null && isDefaultAttributeSupported(flow.getSourceRef());
      return canUpdate;
    }

    @Override
    public IReason updateNeeded(IUpdateContext context) {
      IPeService peService = Graphiti.getPeService();
      String property = peService.getPropertyValue(context.getPictogramElement(), IS_DEFAULT_FLOW_PROPERTY);
      if (property == null || !canUpdate(context)) {
        return Reason.createFalseReason();
      }
      SequenceFlow flow = BusinessObjectUtil.getFirstElementOfType(context.getPictogramElement(),
          SequenceFlow.class);
      SequenceFlow defaultFlow = getDefaultFlow(flow.getSourceRef());
      boolean isDefault = defaultFlow == null ? false : defaultFlow.equals(flow);
      boolean changed = isDefault != new Boolean(property);
      return changed ? Reason.createTrueReason() : Reason.createFalseReason();
    }

    @Override
    public boolean update(IUpdateContext context) {
      Connection connection = (Connection) context.getPictogramElement();
      setDefaultSequenceFlow(connection);
      return true;
    }
  }

  private static void setConditionalSequenceFlow(Connection connection) {
    IPeService peService = Graphiti.getPeService();
    SequenceFlow flow = BusinessObjectUtil.getFirstElementOfType(connection, SequenceFlow.class);

    Tuple<ConnectionDecorator, ConnectionDecorator> decorators = getConnectionDecorators(connection);
    ConnectionDecorator def = decorators.getFirst();
    ConnectionDecorator cond = decorators.getSecond();

    if (flow.getConditionExpression() != null && flow.getSourceRef() instanceof Activity && def == null) {
      ConnectionDecorator decorator = createConditionalConnectionDecorator(connection);
      GraphicsAlgorithm ga = decorator.getGraphicsAlgorithm();
      ga.setFilled(true);
      ga.setForeground(manageColor(connection, StyleUtil.CLASS_FOREGROUND));
      ga.setBackground(manageColor(connection, IColorConstant.WHITE));
    } else if (cond != null) {
      peService.deletePictogramElement(cond);
    }

    peService.setPropertyValue(connection, IS_CONDITIONAL_FLOW_PROPERTY,
        Boolean.toString(flow.getConditionExpression() != null));
  }
 
  public static class UpdateConditionalSequenceFlowFeature extends AbstractUpdateFeature {

    public UpdateConditionalSequenceFlowFeature(IFeatureProvider fp) {
      super(fp);
    }

    @Override
    public boolean canUpdate(IUpdateContext context) {
      SequenceFlow flow = BusinessObjectUtil.getFirstElementOfType(context.getPictogramElement(),
          SequenceFlow.class);
      boolean canUpdate = flow != null && flow.getSourceRef() instanceof Activity;
      return canUpdate;
    }

    @Override
    public IReason updateNeeded(IUpdateContext context) {
      // NOTE: if this method returns "true" the very first time it's called by the refresh
      // framework, the connection line will be drawn as a red dotted line, so make sure
      // all properties have been correctly set to their initial values in the AddFeature!
      // see https://issues.jboss.org/browse/JBPM-3102
      IPeService peService = Graphiti.getPeService();
      Connection connection = (Connection) context.getPictogramElement();
      SequenceFlow flow = BusinessObjectUtil.getFirstElementOfType(connection, SequenceFlow.class);
      String property = peService.getPropertyValue(connection, IS_CONDITIONAL_FLOW_PROPERTY);
      if (property == null || !canUpdate(context)) {
        return Reason.createFalseReason();
      }
      boolean changed = flow.getConditionExpression() != null != new Boolean(property);
      return changed ? Reason.createTrueReason() : Reason.createFalseReason();
    }

    @Override
    public boolean update(IUpdateContext context) {
      Connection connection = (Connection) context.getPictogramElement();
      setConditionalSequenceFlow(connection);
      return true;
    }
  }
 
  public static class SequenceFlowReconnectionFeature extends BaseElementReconnectionFeature {

    public SequenceFlowReconnectionFeature(IFeatureProvider fp) {
      super(fp);
      // TODO Auto-generated constructor stub
    }

    @Override
    public boolean canReconnect(IReconnectionContext context) {
      if (super.canReconnect(context)) {
        BaseElement targetElement = BusinessObjectUtil.getFirstElementOfType(context.getTargetPictogramElement(), BaseElement.class);
        return targetElement instanceof FlowNode;
      }
      return false;
    }

//    @Override
//    public void postReconnect(IReconnectionContext context) {
//      super.postReconnect(context);
//      SequenceFlow flow = BusinessObjectUtil.getFirstElementOfType(context.getConnection(), SequenceFlow.class);
//      FlowNode targetElement = BusinessObjectUtil.getFirstElementOfType(context.getTargetPictogramElement(), FlowNode.class);
//      if (context.getReconnectType().equals(ReconnectionContext.RECONNECT_TARGET)) {
//        flow.setTargetRef(targetElement);
//      }
//      else {
//        flow.setSourceRef(targetElement);
//      }
//    }
  }
 
  private static boolean isDefaultAttributeSupported(FlowNode node) {
    if (node instanceof Activity) {
      return true;
    }
    if (node instanceof ExclusiveGateway || node instanceof InclusiveGateway || node instanceof ComplexGateway) {
      return true;
    }
    return false;
  }

  private static SequenceFlow getDefaultFlow(FlowNode node) {
    if (isDefaultAttributeSupported(node)) {
      try {
        return (SequenceFlow) node.getClass().getMethod("getDefault").invoke(node);
      } catch (Exception e) {
        Activator.logError(e);
      }
    }
    return null;
  }

  private static Tuple<ConnectionDecorator, ConnectionDecorator> getConnectionDecorators(Connection connection) {
    IPeService peService = Graphiti.getPeService();

    ConnectionDecorator defaultDecorator = null;
    ConnectionDecorator conditionalDecorator = null;

    Iterator<ConnectionDecorator> iterator = connection.getConnectionDecorators().iterator();
    while (iterator.hasNext()) {
      ConnectionDecorator connectionDecorator = iterator.next();
      String defProp = peService.getPropertyValue(connectionDecorator, DEFAULT_MARKER_PROPERTY);
      if (defProp != null && new Boolean(defProp)) {
        defaultDecorator = connectionDecorator;
        continue;
      }
      String condProp = peService.getPropertyValue(connectionDecorator, CONDITIONAL_MARKER_PROPERTY);
      if (condProp != null && new Boolean(condProp)) {
        conditionalDecorator = connectionDecorator;
      }
    }

    return new Tuple<ConnectionDecorator, ConnectionDecorator>(defaultDecorator, conditionalDecorator);
  }

  private static ConnectionDecorator createDefaultConnectionDecorator(Connection connection) {
    ConnectionDecorator marker = Graphiti.getPeService().createConnectionDecorator(connection, false, 0.0, true);
    Graphiti.getGaService().createPolyline(marker, new int[] { -5, 5, -10, -5 });
    Graphiti.getPeService().setPropertyValue(marker, DEFAULT_MARKER_PROPERTY, Boolean.toString(true));
    return marker;
  }

  private static ConnectionDecorator createConditionalConnectionDecorator(Connection connection) {
    ConnectionDecorator marker = Graphiti.getPeService().createConnectionDecorator(connection, false, 0.0, true);
    Graphiti.getGaService().createPolygon(marker, new int[] { -15, 0, -7, 5, 0, 0, -7, -5 });
    Graphiti.getPeService().setPropertyValue(marker, CONDITIONAL_MARKER_PROPERTY, Boolean.toString(true));
    return marker;
  }
}
TOP

Related Classes of org.eclipse.bpmn2.modeler.ui.features.flow.SequenceFlowFeatureContainer$SequenceFlowReconnectionFeature

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.