///<inheritdoc/> protected override void SetupHandler() { CreateRouter(); // tab layout var layoutGroup = Handler.AddGroup(LAYOUT); Scope scope = router.Scope; layoutGroup.AddList(SCOPE, scopeTypes, scopeTypes[scope == Scope.RouteAllEdges ? 0 : 1]); layoutGroup.AddList(OPTIMIZATION_STRATEGY, strategies, strategies[0]); layoutGroup.AddList(MONOTONIC_RESTRICTION, monotonyFlags, monotonyFlags[0]); layoutGroup.AddBool(CONSIDER_NODE_LABELS, router.ConsiderNodeLabels); layoutGroup.AddBool(CONSIDER_EDGE_LABELS, router.ConsiderEdgeLabels); layoutGroup.AddBool(ENABLE_REROUTING, router.Rerouting); layoutGroup.AddInt(MAXIMUM_DURATION, 30); // tab distances var distancesGroup = Handler.AddGroup(MINIMAL_DISTANCES); EdgeLayoutDescriptor descriptor = router.DefaultEdgeLayoutDescriptor; distancesGroup.AddDouble(MINIMAL_EDGE_TO_EDGE_DISTANCE, descriptor.MinimumEdgeToEdgeDistance); distancesGroup.AddDouble(MINIMAL_NODE_TO_EDGE_DISTANCE, router.MinimumNodeToEdgeDistance); distancesGroup.AddDouble(MINIMAL_NODE_CORNER_DISTANCE, descriptor.MinimumNodeCornerDistance); distancesGroup.AddDouble(MINIMAL_FIRST_SEGMENT_LENGTH, descriptor.MinimumFirstSegmentLength); distancesGroup.AddDouble(MINIMAL_LAST_SEGMENT_LENGTH, descriptor.MinimumLastSegmentLength); // tab grid var gridGroup = Handler.AddGroup(GRID_SETTINGS); Grid grid = router.Grid; var gridEnabledItem = gridGroup.AddBool(GRID_ENABLED, grid != null); var gridSpacingItem = gridGroup.AddDouble(GRID_SPACING, grid != null ? grid.Spacing : 10); // tab polyline routing var polylineGroup = Handler.AddGroup(POLYLINE_ROUTING); var polyLineItem = polylineGroup.AddBool(ENABLE_POLYLINE_ROUTING, true); var polyLineSegmentLengthItem = polylineGroup.AddDouble(PREFERRED_POLYLINE_SEGMENT_LENGTH, router.PreferredPolylineSegmentLength); // some constraints to enable/disable values that depends on other values ConstraintManager cm = new ConstraintManager(Handler); cm.SetEnabledOnValueEquals(gridEnabledItem, true, gridSpacingItem); cm.SetEnabledOnValueEquals(polyLineItem, true, polyLineSegmentLengthItem); }
private void AddMinimumEdgeLength(double minimumEdgeLength) { // each edge should have a minimum length so that all its labels can be placed on it one // after another with a minimum label-to-label distance EdgeLayoutDescriptors.Delegate = edge => { var descriptor = new EdgeLayoutDescriptor { RoutingStyle = new RoutingStyle(EdgeRoutingStyle.Orthogonal) }; double minLength = 0; foreach (var label in edge.Labels) { var labelSize = label.GetLayout().GetBounds(); minLength += Math.Max(labelSize.Width, labelSize.Height); } if (edge.Labels.Count > 1) { minLength += (edge.Labels.Count - 1) * MinLabelToLabelDistance; } descriptor.MinimumLength = Math.Max(minLength, minimumEdgeLength); return(descriptor); }; }
protected override LayoutData CreateConfiguredLayoutData(GraphControl graphControl, ILayoutAlgorithm layout) { var layoutData = new EdgeRouterData(); layoutData.EdgeLayoutDescriptors.Delegate = edge => { var descriptor = new EdgeLayoutDescriptor { MinimumEdgeToEdgeDistance = MinimumEdgeToEdgeDistanceItem, MinimumNodeCornerDistance = MinimumNodeCornerDistanceItem, MinimumFirstSegmentLength = MinimumFirstSegmentLengthItem, MinimumLastSegmentLength = MinimumLastSegmentLengthItem, PreferredOctilinearSegmentLength = PreferredOctilinearSegmentLengthItem, MaximumOctilinearSegmentRatio = PreferredPolylineSegmentRatioItem, SourceCurveConnectionStyle = SourceConnectionStyleItem, TargetCurveConnectionStyle = TargetConnectionStyleItem, CurveUTurnSymmetry = CurveUTurnSymmetryItem, CurveShortcuts = CurveShortcutsItem, RoutingStyle = EdgeRoutingStyleItem, RoutingPolicy = RoutingPolicyItem, }; if (OptimizationStrategyItem == EnumStrategies.Balanced) { descriptor.PenaltySettings = PenaltySettings.OptimizationBalanced; } else if (OptimizationStrategyItem == EnumStrategies.MinimizeBends) { descriptor.PenaltySettings = PenaltySettings.OptimizationEdgeBends; } else if (OptimizationStrategyItem == EnumStrategies.MinimizeEdgeLength) { descriptor.PenaltySettings = PenaltySettings.OptimizationEdgeLengths; } else { descriptor.PenaltySettings = PenaltySettings.OptimizationEdgeCrossings; } if (MonotonicRestrictionItem == EnumMonotonyFlags.Horizontal) { descriptor.MonotonicPathRestriction = MonotonicPathRestriction.Horizontal; } else if (MonotonicRestrictionItem == EnumMonotonyFlags.Vertical) { descriptor.MonotonicPathRestriction = MonotonicPathRestriction.Vertical; } else if (MonotonicRestrictionItem == EnumMonotonyFlags.Both) { descriptor.MonotonicPathRestriction = MonotonicPathRestriction.Both; } else { descriptor.MonotonicPathRestriction = MonotonicPathRestriction.None; } descriptor.MinimumEdgeToEdgeDistance = MinimumEdgeToEdgeDistanceItem; descriptor.MinimumNodeCornerDistance = MinimumNodeCornerDistanceItem; descriptor.MinimumFirstSegmentLength = MinimumFirstSegmentLengthItem; descriptor.MinimumLastSegmentLength = MinimumLastSegmentLengthItem; if (UseIntermediatePointsItem) { descriptor.IntermediateRoutingPoints = edge.Bends .Select(b => new YPoint(b.Location.X, b.Location.Y)) .Cast <object>() .ToList(); } return(descriptor); }; var selection = graphControl.Selection; if (ScopeItem == Scope.RouteEdgesAtAffectedNodes) { layoutData.AffectedNodes.Source = selection.SelectedNodes; } else if (ScopeItem == Scope.RouteAffectedEdges) { layoutData.AffectedEdges.Source = selection.SelectedEdges; } else { layoutData.AffectedEdges.Delegate = edge => true; layoutData.AffectedNodes.Delegate = node => true; } if (PortSidesItem != PortSides.Any) { PortCandidate[] candidates; if (PortSidesItem == PortSides.LeftRight) { candidates = new[] { PortCandidate.CreateCandidate(PortDirections.East), PortCandidate.CreateCandidate(PortDirections.West) }; } else { candidates = new[] { PortCandidate.CreateCandidate(PortDirections.North), PortCandidate.CreateCandidate(PortDirections.South) }; } layoutData.SourcePortCandidates.Constant = candidates; layoutData.TargetPortCandidates.Constant = candidates; } switch (BusRoutingItem) { case EnumBusRouting.SingleBus: // All edges in a single bus layoutData.Buses.Add(CreateBusDescriptor()).Delegate = edge => true; break; case EnumBusRouting.ByLabel: var byLabel = new Dictionary <string, List <IEdge> >(); foreach (var edge in graphControl.Graph.Edges) { if (edge.Labels.Count > 0) { var label = edge.Labels[0].Text; List <IEdge> list; if (!byLabel.TryGetValue(label, out list)) { list = new List <IEdge>(); byLabel[label] = list; } list.Add(edge); } } foreach (var edges in byLabel.Values) { // Add a bus per label. Unlabeled edges don't get grouped into a bus layoutData.Buses.Add(CreateBusDescriptor()).Source = edges; } break; case EnumBusRouting.ByColor: var comparer = new ColorComparer(); var byColor = new Dictionary <Brush, List <IEdge> >(comparer); foreach (var edge in graphControl.Graph.Edges) { var brush = ((PolylineEdgeStyle)edge.Style).Pen.Brush; if (!comparer.Equals(brush, Brushes.Black)) { List <IEdge> list; if (!byColor.TryGetValue(brush, out list)) { list = new List <IEdge>(); byColor[brush] = list; } list.Add(edge); } } foreach (var edges in byColor.Values) { // Add a bus per color. Black edges don't get grouped into a bus layoutData.Buses.Add(CreateBusDescriptor()).Source = edges; } break; } return(layoutData.CombineWith( CreateLabelingLayoutData( graphControl.Graph, LabelPlacementAlongEdgeItem, LabelPlacementSideOfEdgeItem, LabelPlacementOrientationItem, LabelPlacementDistanceItem ) )); }
///<inheritdoc/> protected override void ConfigureLayout() { EdgeLayoutDescriptor descriptor = router.DefaultEdgeLayoutDescriptor; OptionGroup layoutGroup = Handler.GetGroupByName(LAYOUT); OptionGroup gridGroup = Handler.GetGroupByName(GRID_SETTINGS); OptionGroup polylineGroup = Handler.GetGroupByName(POLYLINE_ROUTING); OptionGroup distancesGroup = Handler.GetGroupByName(MINIMAL_DISTANCES); string scope = (string)layoutGroup[SCOPE].Value; if (scope.Equals(SCOPE_ALL_EDGES)) { router.Scope = Scope.RouteAllEdges; } else { router.Scope = Scope.RouteAffectedEdges; } string strategy = (string)layoutGroup[OPTIMIZATION_STRATEGY].Value; if (strategy == STRATEGY_BALANCED) { descriptor.PenaltySettings = PenaltySettings.OptimizationBalanced; } else if (strategy == STRATEGY_MINIMIZE_BENDS) { descriptor.PenaltySettings = PenaltySettings.OptimizationEdgeBends; } else if (strategy == STRATEGY_MINIMIZE_EDGE_LENGTH) { descriptor.PenaltySettings = PenaltySettings.OptimizationEdgeLengths; } else { descriptor.PenaltySettings = PenaltySettings.OptimizationEdgeCrossings; } string monotonyFlag = (string)layoutGroup[MONOTONIC_RESTRICTION].Value; if (monotonyFlag == MONOTONIC_HORIZONTAL) { descriptor.MonotonicPathRestriction = MonotonicPathRestriction.Horizontal; } else if (monotonyFlag == MONOTONIC_VERTICAL) { descriptor.MonotonicPathRestriction = MonotonicPathRestriction.Vertical; } else { descriptor.MonotonicPathRestriction = MonotonicPathRestriction.None; } descriptor.MinimumEdgeToEdgeDistance = (double)distancesGroup[MINIMAL_EDGE_TO_EDGE_DISTANCE].Value; router.MinimumNodeToEdgeDistance = (double)distancesGroup[MINIMAL_NODE_TO_EDGE_DISTANCE].Value; descriptor.MinimumNodeCornerDistance = (double)distancesGroup[MINIMAL_NODE_CORNER_DISTANCE].Value; descriptor.MinimumFirstSegmentLength = (double)distancesGroup[MINIMAL_FIRST_SEGMENT_LENGTH].Value; descriptor.MinimumLastSegmentLength = (double)distancesGroup[MINIMAL_LAST_SEGMENT_LENGTH].Value; if ((bool)gridGroup[GRID_ENABLED].Value) { double gridSpacing = (double)gridGroup[GRID_SPACING].Value; router.Grid = new Grid(0, 0, gridSpacing); } else { router.Grid = null; } router.ConsiderNodeLabels = (bool)layoutGroup[CONSIDER_NODE_LABELS].Value; router.ConsiderEdgeLabels = (bool)layoutGroup[CONSIDER_EDGE_LABELS].Value; router.Rerouting = (bool)layoutGroup[ENABLE_REROUTING].Value; router.PolylineRouting = (bool)polylineGroup[ENABLE_POLYLINE_ROUTING].Value; router.PreferredPolylineSegmentLength = (double)polylineGroup[PREFERRED_POLYLINE_SEGMENT_LENGTH].Value; router.MaximumDuration = (int)layoutGroup[MAXIMUM_DURATION].Value * 1000; LayoutAlgorithm = router; }
///<inheritdoc/> protected override void ConfigureLayout() { LayoutGraph graph = CurrentLayoutGraph; HierarchicLayout hl = new HierarchicLayout(); LayoutAlgorithm = hl; // mark incremental elements if required IDataMap incrementalElements; OptionGroup generalGroup = (OptionGroup)Handler.GetGroupByName(GENERAL); OptionGroup currentGroup = (OptionGroup)generalGroup.GetGroupByName(INTERACTION); OptionGroup groupingGroup = (OptionGroup)Handler.GetGroupByName(GROUPING); bool fromSketch = (bool)currentGroup[USE_DRAWING_AS_SKETCH].Value; bool incrementalLayout = (bool)currentGroup[SELECTED_ELEMENTS_INCREMENTALLY].Value; bool selectedElements = !IsEdgeSelectionEmpty() || !IsNodeSelectionEmpty(); if (incrementalLayout && selectedElements) { // create storage for both nodes and edges incrementalElements = Maps.CreateHashedDataMap(); // configure the mode hl.LayoutMode = LayoutMode.Incremental; IIncrementalHintsFactory ihf = hl.CreateIncrementalHintsFactory(); foreach (Node node in graph.Nodes) { if (IsSelected(node)) { incrementalElements.Set(node, ihf.CreateLayerIncrementallyHint(node)); } } foreach (Edge edge in graph.Edges) { if (IsSelected(edge)) { incrementalElements.Set(edge, ihf.CreateSequenceIncrementallyHint(edge)); } } graph.AddDataProvider(HierarchicLayout.IncrementalHintsDpKey, incrementalElements); } else if (fromSketch) { hl.LayoutMode = LayoutMode.Incremental; } else { hl.LayoutMode = LayoutMode.FromScratch; } // cast to implementation simplex var np = (SimplexNodePlacer)hl.NodePlacer; np.BarycenterMode = (bool)generalGroup[SYMMETRIC_PLACEMENT].Value; np.StraightenEdges = (bool)Handler.GetValue(EDGE_SETTINGS, EDGE_STRAIGHTENING_OPTIMIZATION_ENABLED); hl.ComponentLayoutEnabled = (bool)generalGroup[LAYOUT_COMPONENTS_SEPARATELY].Value; currentGroup = (OptionGroup)generalGroup.GetGroupByName(MINIMUM_DISTANCES); hl.MinimumLayerDistance = (double)currentGroup[MINIMUM_LAYER_DISTANCE].Value; hl.NodeToEdgeDistance = (double)currentGroup[NODE_TO_EDGE_DISTANCE].Value; hl.NodeToNodeDistance = (double)currentGroup[NODE_TO_NODE_DISTANCE].Value; hl.EdgeToEdgeDistance = (double)currentGroup[EDGE_TO_EDGE_DISTANCE].Value; NodeLayoutDescriptor nld = hl.NodeLayoutDescriptor; EdgeLayoutDescriptor eld = hl.EdgeLayoutDescriptor; currentGroup = (OptionGroup)Handler.GetGroupByName(EDGE_SETTINGS); hl.AutomaticEdgeGrouping = (bool)currentGroup[AUTOMATIC_EDGE_GROUPING_ENABLED].Value; string edgeRoutingChoice = (string)currentGroup[EDGE_ROUTING].Value; eld.RoutingStyle = edgeRoutingEnum[edgeRoutingChoice]; eld.MinimumFirstSegmentLength = (double)currentGroup[MINIMUM_FIRST_SEGMENT_LENGTH].Value; eld.MinimumLastSegmentLength = (double)currentGroup[MINIMUM_LAST_SEGMENT_LENGTH].Value; eld.MinimumDistance = (double)currentGroup[MINIMUM_EDGE_DISTANCE].Value; eld.MinimumLength = (double)currentGroup[MINIMUM_EDGE_LENGTH].Value; eld.MinimumSlope = (double)currentGroup[MINIMUM_SLOPE].Value; eld.SourcePortOptimization = (bool)currentGroup[PC_OPTIMIZATION_ENABLED].Value; eld.TargetPortOptimization = (bool)currentGroup[PC_OPTIMIZATION_ENABLED].Value; var isIncrementalModeEnabled = (fromSketch || (incrementalLayout && selectedElements)); var recursiveRoutingMode = Handler.GetValue(EDGE_SETTINGS, RECURSIVE_EDGE_ROUTING); if (!isIncrementalModeEnabled && recursiveRoutingMode == RECURSIVE_EDGE_ROUTING_DIRECTED) { eld.RecursiveEdgeStyle = RecursiveEdgeStyle.Directed; } else if (!isIncrementalModeEnabled && recursiveRoutingMode == RECURSIVE_EDGE_ROUTING_UNDIRECTED) { eld.RecursiveEdgeStyle = RecursiveEdgeStyle.Undirected; } else { eld.RecursiveEdgeStyle = RecursiveEdgeStyle.Off; } nld.MinimumDistance = Math.Min(hl.NodeToNodeDistance, hl.NodeToEdgeDistance); nld.MinimumLayerHeight = 0; OptionGroup rankGroup = (OptionGroup)Handler.GetGroupByName(RANKS); string layerAlignmentChoice = (string)rankGroup[LAYER_ALIGNMENT].Value; nld.LayerAlignment = alignmentEnum[layerAlignmentChoice]; ol = (OrientationLayout)hl.OrientationLayout; string orientationChoice = (string)generalGroup[ORIENTATION].Value; ol.Orientation = orientEnum[orientationChoice]; OptionGroup labelingGroup = (OptionGroup)Handler.GetGroupByName(LABELING); currentGroup = (OptionGroup)labelingGroup.GetGroupByName(LABELING_EDGE_PROPERTIES); string el = (string)currentGroup[EDGE_LABELING].Value; if (!el.Equals(EDGE_LABELING_NONE)) { if (el.Equals(EDGE_LABELING_GENERIC)) { var la = new GenericLabeling(); la.MaximumDuration = 0; la.PlaceNodeLabels = false; la.PlaceEdgeLabels = true; la.AutoFlipping = true; la.ProfitModel = new SimpleProfitModel(); hl.PrependStage(la); } else if (el.Equals(EDGE_LABELING_HIERARCHIC)) { bool copactEdgeLabelPlacement = (bool)currentGroup[COMPACT_EDGE_LABEL_PLACEMENT].Value; if (hl.NodePlacer is SimplexNodePlacer) { np.LabelCompaction = copactEdgeLabelPlacement; } hl.IntegratedEdgeLabeling = true; } } else { hl.IntegratedEdgeLabeling = false; } currentGroup = (OptionGroup)labelingGroup.GetGroupByName(NODE_PROPERTIES); if ((bool)currentGroup[CONSIDER_NODE_LABELS].Value) { hl.ConsiderNodeLabels = true; hl.NodeLayoutDescriptor.NodeLabelMode = NodeLabelMode.ConsiderForDrawing; } else { hl.ConsiderNodeLabels = false; } string rp = (string)rankGroup[RANKING_POLICY].Value; hl.FromScratchLayeringStrategy = rankingPolicies[rp]; if (rp.Equals(BFS_LAYERS)) { CurrentLayoutGraph.AddDataProvider(BFSLayerer.CoreNodesDpKey, new SelectedNodesDP(this)); } hl.ComponentArrangementPolicy = componentAlignmentEnum[(string)rankGroup[COMPONENT_ARRANGEMENT_POLICY].Value]; //configure AsIsLayerer Object layerer = (hl.LayoutMode == LayoutMode.FromScratch) ? hl.FromScratchLayerer : hl.FixedElementsLayerer; // if (layerer is OldLayererWrapper) { // layerer = ((OldLayererWrapper)layerer).OldLayerer; // } if (layerer is AsIsLayerer) { AsIsLayerer ail = (AsIsLayerer)layerer; currentGroup = (OptionGroup)rankGroup.GetGroupByName(FROM_SKETCH_PROPERTIES); ail.NodeHalo = (double)currentGroup[HALO].Value; ail.NodeScalingFactor = (double)currentGroup[SCALE].Value; ail.MinimumNodeSize = (double)currentGroup[MINIMUM_SIZE].Value; ail.MaximumNodeSize = (double)currentGroup[MAXIMUM_SIZE].Value; } //configure grouping np.GroupCompactionStrategy = groupHorizCompactionEnum[(string)groupingGroup[GROUP_HORIZONTAL_COMPACTION].Value]; if (!fromSketch && groupStrategyEnum[(string)groupingGroup[GROUP_LAYERING_STRATEGY].Value]) { GroupAlignmentPolicy alignmentPolicy = groupAlignmentEnum[(string)groupingGroup[GROUP_ALIGNMENT].Value]; hl.GroupAlignmentPolicy = alignmentPolicy; hl.CompactGroups = (bool)groupingGroup[GROUP_ENABLE_COMPACTION].Value; hl.RecursiveGroupLayering = true; } else { hl.RecursiveGroupLayering = false; } OptionGroup swimGroup = (OptionGroup)Handler.GetGroupByName(SWIMLANES); if ((bool)swimGroup[TREAT_ROOT_GROUPS_AS_SWIMLANES].Value) { TopLevelGroupToSwimlaneStage stage = new TopLevelGroupToSwimlaneStage(); stage.OrderSwimlanesFromSketch = (bool)swimGroup[USE_ORDER_FROM_SKETCH].Value; stage.Spacing = (double)swimGroup[SWIMLANE_SPACING].Value; hl.AppendStage(stage); } hl.BackLoopRouting = (bool)Handler.GetValue(EDGE_SETTINGS, BACKLOOP_ROUTING); hl.MaximumDuration = ((int)Handler.GetValue(GENERAL, MAXIMUM_DURATION)) * 1000; bool gridEnabled = (bool)Handler.GetValue(GRID, GRID_ENABLED); if (gridEnabled) { hl.GridSpacing = (double)Handler.GetValue(GRID, GRID_SPACING); String portAssignment = (string)Handler.GetValue(GRID, GRID_PORT_ASSIGNMENT); PortAssignmentMode gridPortAssignment; switch (portAssignment) { case GRID_PORT_ASSIGNMENT_ON_GRID: gridPortAssignment = PortAssignmentMode.OnGrid; break; case GRID_PORT_ASSIGNMENT_ON_SUBGRID: gridPortAssignment = PortAssignmentMode.OnSubgrid; break; default: gridPortAssignment = PortAssignmentMode.Default; break; } graph.AddDataProvider(HierarchicLayoutCore.NodeLayoutDescriptorDpKey, new NodeLayoutDescriptorAdapter(hl.NodeLayoutDescriptor, graph, gridPortAssignment)); } }