private static void AddEdgeLabelPlacementDescriptors(LayoutGraphAdapter adapter) { var atSourceDescriptor = new PreferredPlacementDescriptor { PlaceAlongEdge = LabelPlacements.AtSourcePort, SideOfEdge = LabelPlacements.LeftOfEdge | LabelPlacements.RightOfEdge, }; adapter.AddDataProvider(LayoutGraphAdapter.EdgeLabelLayoutPreferredPlacementDescriptorDpKey, Mappers.FromDelegate((ILabel label) => { var edgeType = ((BpmnEdgeStyle)((IEdge)label.Owner).Style).Type; if (edgeType == EdgeType.SequenceFlow || edgeType == EdgeType.DefaultFlow || edgeType == EdgeType.ConditionalFlow) { // labels on sequence, default and conditional flow edges should be placed at the source side. return(atSourceDescriptor); } return(null); })); }
protected override void Apply(LayoutGraphAdapter adapter, ILayoutAlgorithm layout, CopiedLayoutGraph layoutGraph) { var graph = adapter.AdaptedGraph; // check if only selected elements should be laid out var layoutOnlySelection = layout is BpmnLayout && ((BpmnLayout)layout).Scope == Scope.SelectedElements; // mark 'flow' edges, i.e. sequence flows, default flows and conditional flows adapter.AddDataProvider(BpmnLayout.SequenceFlowEdgesDpKey, Mappers.FromDelegate <IEdge, bool>(IsSequenceFlow)); // mark boundary interrupting edges for the BalancingPortOptimizer adapter.AddDataProvider(BpmnLayout.BoundaryInterruptingEdgesDpKey, Mappers.FromDelegate((IEdge edge) => edge.SourcePort.Style is EventPortStyle)); // mark conversations, events and gateways so their port locations are adjusted adapter.AddDataProvider(PortLocationAdjuster.AffectedNodesDpKey, Mappers.FromDelegate((INode node) => (node.Style is ConversationNodeStyle || node.Style is EventNodeStyle || node.Style is GatewayNodeStyle))); // add NodeHalos around nodes with event ports or specific exterior labels so the layout keeps space for the event ports and labels as well AddNodeHalos(adapter, graph, layoutOnlySelection); // add PreferredPlacementDescriptors for labels on sequence, default or conditional flows to place them at source side AddEdgeLabelPlacementDescriptors(adapter); // mark nodes, edges and labels as either fixed or affected by the layout and configure port constraints and incremental hints MarkFixedAndAffectedItems(adapter, layoutOnlySelection); // mark associations and message flows as undirected so they have less impact on layering EdgeDirectedness.Delegate = edge => (IsMessageFlow(edge) || IsAssociation(edge)) ? 0 : 1; // add layer constraints for start events, sub processes and message flows AddLayerConstraints(graph); // add EdgeLayoutDescriptor to specify minimum edge length for edges AddMinimumEdgeLength(MinimumEdgeLength); base.Apply(adapter, layout, layoutGraph); }
private async void StartAnimation() { // animates the nodes in random fashion Random r = new Random(DateTime.Now.TimeOfDay.Milliseconds); await animator.Animate(Animations.CreateGraphAnimation(graphControl.Graph, Mappers.FromDelegate <INode, IRectangle>(node => new RectD(r.NextDouble() * 800, r.NextDouble() * 800, node.Layout.Width, node.Layout.Height)), null, null, null, TimeSpan.FromSeconds(5))); }
private void MarkFixedAndAffectedItems(LayoutGraphAdapter adapter, bool layoutOnlySelection) { if (layoutOnlySelection) { var affectedEdges = Mappers.FromDelegate((IEdge edge) => adapter.SelectionModel.IsSelected(edge) || adapter.SelectionModel.IsSelected(edge.GetSourceNode()) || adapter.SelectionModel.IsSelected(edge.GetTargetNode())); adapter.AddDataProvider(LayoutKeys.AffectedEdgesDpKey, affectedEdges); // fix ports of unselected edges and edges at event ports adapter.AddDataProvider(PortConstraintKeys.SourcePortConstraintDpKey, Mappers.FromDelegate <IEdge, PortConstraint>( edge => (!affectedEdges[edge] || edge.SourcePort.Style is EventPortStyle) ? PortConstraint.Create(GetSide(edge, true)) : null)); adapter.AddDataProvider(PortConstraintKeys.TargetPortConstraintDpKey, Mappers.FromDelegate <IEdge, PortConstraint>( edge => !affectedEdges[edge] ? PortConstraint.Create(GetSide(edge, false)) : null)); // give core layout hints that selected nodes and edges should be incremental IncrementalHints.ContextDelegate = (item, factory) => { if (item is INode && adapter.SelectionModel.IsSelected(item)) { return(factory.CreateLayerIncrementallyHint(item)); } else if (item is IEdge && affectedEdges[(IEdge)item]) { return(factory.CreateSequenceIncrementallyHint(item)); } return(null); }; adapter.AddDataProvider(BpmnLayout.AffectedLabelsDpKey, Mappers.FromDelegate <ILabel, bool>(label => { var edge = label.Owner as IEdge; if (edge != null) { return(affectedEdges[edge]); } var node = label.Owner as INode; if (node != null) { var isInnerLabel = node.Layout.Contains(label.GetLayout().GetCenter()); bool isPool = node.Style is PoolNodeStyle; bool isChoreography = node.Style is ChoreographyNodeStyle; return(!isInnerLabel && !isPool && !isChoreography && adapter.SelectionModel.IsSelected(node)); } return(false); })); } else { // fix source port of edges at event ports adapter.AddDataProvider(PortConstraintKeys.SourcePortConstraintDpKey, Mappers.FromDelegate <IEdge, PortConstraint>( edge => edge.SourcePort.Style is EventPortStyle ? PortConstraint.Create(GetSide(edge, true)) : null)); adapter.AddDataProvider(BpmnLayout.AffectedLabelsDpKey, Mappers.FromDelegate <ILabel, bool>(label => { if (label.Owner is IEdge) { return(true); } var node = label.Owner as INode; if (node != null) { var isInnerLabel = node.Layout.Contains(label.GetLayout().GetCenter()); bool isPool = node.Style is PoolNodeStyle; bool isChoreography = node.Style is ChoreographyNodeStyle; return(!isInnerLabel && !isPool && !isChoreography); } return(false); })); } }
private static void MarkFixedAndAffectedItems(GenericLayoutData data, HierarchicLayoutData hierarchicLayoutData, ISelectionModel <IModelItem> graphSelection, bool layoutOnlySelection) { if (layoutOnlySelection) { var affectedEdges = Mappers.FromDelegate((IEdge edge) => graphSelection.IsSelected(edge) || graphSelection.IsSelected(edge.GetSourceNode()) || graphSelection.IsSelected(edge.GetTargetNode())); data.AddItemCollection(LayoutKeys.AffectedEdgesDpKey).Mapper = affectedEdges; // fix ports of unselected edges and edges at event ports data.AddItemMapping(PortConstraintKeys.SourcePortConstraintDpKey).Delegate = edge => (!affectedEdges[edge] || edge.SourcePort.Style is EventPortStyle) ? PortConstraint.Create(GetSide(edge, true)) : null; data.AddItemMapping(PortConstraintKeys.TargetPortConstraintDpKey).Delegate = edge => !affectedEdges[edge] ? PortConstraint.Create(GetSide(edge, false)) : null; // give core layout hints that selected nodes and edges should be incremental hierarchicLayoutData.IncrementalHints.ContextDelegate = (item, factory) => { if (item is INode && graphSelection.IsSelected(item)) { return(factory.CreateLayerIncrementallyHint(item)); } else if (item is IEdge && affectedEdges[(IEdge)item]) { return(factory.CreateSequenceIncrementallyHint(item)); } return(null); }; data.AddItemCollection(BpmnLayout.AffectedLabelsDpKey).Delegate = label => { var edge = label.Owner as IEdge; if (edge != null) { return(affectedEdges[edge]); } var node = label.Owner as INode; if (node != null) { var isInnerLabel = node.Layout.Contains(label.GetLayout().GetCenter()); bool isPool = node.Style is PoolNodeStyle; bool isChoreography = node.Style is ChoreographyNodeStyle; return(!isInnerLabel && !isPool && !isChoreography && graphSelection.IsSelected(node)); } return(false); }; } else { // fix source port of edges at event ports data.AddItemMapping(PortConstraintKeys.SourcePortConstraintDpKey).Delegate = edge => edge.SourcePort.Style is EventPortStyle?PortConstraint.Create(GetSide(edge, true)) : null; data.AddItemCollection(BpmnLayout.AffectedLabelsDpKey).Delegate = label => { if (label.Owner is IEdge) { return(true); } var node = label.Owner as INode; if (node != null) { var isInnerLabel = node.Layout.Contains(label.GetLayout().GetCenter()); bool isPool = node.Style is PoolNodeStyle; bool isChoreography = node.Style is ChoreographyNodeStyle; return(!isInnerLabel && !isPool && !isChoreography); } return(false); }; } }