protected override LayoutData CreateConfiguredLayoutData(GraphControl graphControl, ILayoutAlgorithm layout) { var layoutData = new BusRouterData(); var graph = graphControl.Graph; var graphSelection = graphControl.Selection; var scopePartial = ScopeItem == EnumScope.Partial; var busIds = layoutData.EdgeDescriptors.Mapper; foreach (var edge in graph.Edges) { var isFixed = scopePartial && !graphSelection.IsSelected(edge.GetSourceNode()) && !graphSelection.IsSelected(edge.GetTargetNode()); var id = GetBusId(edge, BusesItem); var descriptor = new BusDescriptor(id, isFixed) { RoutingPolicy = RoutingPolicyItem }; busIds[edge] = descriptor; } HashSet <object> selectedIds; switch (ScopeItem) { case EnumScope.Subset: layoutData.AffectedEdges.Delegate = graphSelection.IsSelected; break; case EnumScope.SubsetBus: selectedIds = new HashSet <object>(graphSelection .SelectedEdges .Select(edge => busIds[edge].BusId)); layoutData.AffectedEdges.Delegate = edge => selectedIds.Contains(busIds[edge].BusId); break; case EnumScope.Partial: selectedIds = new HashSet <object>(graphSelection .SelectedNodes .SelectMany(node => graph.EdgesAt(node)) .Select(edge => busIds[edge].BusId)); layoutData.AffectedEdges.Delegate = edge => selectedIds.Contains(busIds[edge].BusId); var hideNonOrthogonalEdgesLayoutData = new GenericLayoutData(); hideNonOrthogonalEdgesLayoutData.AddItemCollection(HideNonOrthogonalEdgesStage.SelectedNodesDpKey).Source = graphSelection.SelectedNodes; return(layoutData.CombineWith(hideNonOrthogonalEdgesLayoutData)); } return(layoutData); }
public LayoutData Create(IGraph graph, ISelectionModel <IModelItem> selection, Scope layoutScope) { var data = new GenericLayoutData(); var hierarchicLayoutData = new HierarchicLayoutData(); // check if only selected elements should be laid out var layoutOnlySelection = layoutScope == Scope.SelectedElements; // mark 'flow' edges, i.e. sequence flows, default flows and conditional flows data.AddItemCollection(BpmnLayout.SequenceFlowEdgesDpKey).Delegate = IsSequenceFlow; // mark boundary interrupting edges for the BalancingPortOptimizer data.AddItemCollection(BpmnLayout.BoundaryInterruptingEdgesDpKey).Delegate = edge => edge.SourcePort.Style is EventPortStyle; // mark conversations, events and gateways so their port locations are adjusted data.AddItemCollection(PortLocationAdjuster.AffectedNodesDpKey).Delegate = (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(data, graph, selection, layoutOnlySelection); // add PreferredPlacementDescriptors for labels on sequence, default or conditional flows to place them at source side AddEdgeLabelPlacementDescriptors(data); // mark nodes, edges and labels as either fixed or affected by the layout and configure port constraints and incremental hints MarkFixedAndAffectedItems(data, hierarchicLayoutData, selection, layoutOnlySelection); // mark associations and message flows as undirected so they have less impact on layering hierarchicLayoutData.EdgeDirectedness.Delegate = edge => (IsMessageFlow(edge) || IsAssociation(edge)) ? 0 : 1; // add layer constraints for start events, sub processes and message flows AddLayerConstraints(graph, hierarchicLayoutData); // add EdgeLayoutDescriptor to specify minimum edge length for edges AddMinimumEdgeLength(MinimumEdgeLength, hierarchicLayoutData); return(data.CombineWith(hierarchicLayoutData)); }
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); }; } }