/// <summary> /// Creates the layout with an appropriate layout data which is selected by the layout combo box. /// </summary> private void CreateLayout() { switch (layoutComboBox.SelectedIndex) { default: case 0: layout = new HierarchicLayout(); var hierarchicLayoutData = new HierarchicLayoutData(); layoutData = hierarchicLayoutData; abortHandler = hierarchicLayoutData.AbortHandler; break; case 1: layout = new OrganicLayout { QualityTimeRatio = 1.0, MaximumDuration = 1200000, MultiThreadingAllowed = true }; var organicLayoutData = new OrganicLayoutData(); layoutData = organicLayoutData; abortHandler = organicLayoutData.AbortHandler; break; case 2: layout = new OrthogonalLayout { CrossingReduction = true }; var orthogonalLayoutData = new OrthogonalLayoutData(); layoutData = orthogonalLayoutData; abortHandler = orthogonalLayoutData.AbortHandler; break; } }
/// <summary> /// Creates and configures the <see cref="OrganicLayout"/> and the <see cref="OrganicLayoutData"/> /// such that node types are considered. /// </summary> private Sample CreateOrganicSample() { // create an organic layout wrapped by an organic edge router var layout = new OrganicEdgeRouter( // to consider node types, substructures handling (stars, parallel structures and cycles) // on the organic layout is enabled - otherwise types have no influence new OrganicLayout { Deterministic = true, ConsiderNodeSizes = true, MinimumNodeDistance = 30, StarSubstructureStyle = StarSubstructureStyle.Circular, StarSubstructureTypeSeparation = false, ParallelSubstructureStyle = ParallelSubstructureStyle.Rectangular, ParallelSubstructureTypeSeparation = false, CycleSubstructureStyle = CycleSubstructureStyle.Circular }); // the node types are specified as delegate on the nodeTypes property of the layout data var layoutData = new OrganicLayoutData { NodeTypes = { Delegate = node => GetNodeType(node) } }; return(new Sample { Name = "Organic", File = "organic", Layout = layout, LayoutData = layoutData, IsDirected = false }); }
protected override LayoutData CreateConfiguredLayoutData(GraphControl graphControl, ILayoutAlgorithm layout) { var layoutData = new OrganicLayoutData(); switch (GroupLayoutPolicyItem) { case EnumGroupLayoutPolicy.IgnoreGroups: preStage = new HideGroupsStage(); ((MultiStageLayout)layout).PrependStage(preStage); break; case EnumGroupLayoutPolicy.LayoutGroups: //do nothing... break; case EnumGroupLayoutPolicy.FixGroupBounds: layoutData.GroupNodeModes.Delegate = node => graphControl.Graph.IsGroupNode(node) ? GroupNodeMode.FixBounds : GroupNodeMode.Normal; break; case EnumGroupLayoutPolicy.FixGroupContents: layoutData.GroupNodeModes.Delegate = node => graphControl.Graph.IsGroupNode(node) ? GroupNodeMode.FixContents : GroupNodeMode.Normal; break; default: preStage = new HideGroupsStage(); ((MultiStageLayout)layout).PrependStage(preStage); break; } layoutData.AffectedNodes.Source = graphControl.Selection.SelectedNodes; if (EdgeDirectednessItem) { layoutData.EdgeDirectedness.Delegate = edge => { if (edge.Style is IArrowOwner && !Equals(((IArrowOwner)edge.Style).TargetArrow, Arrows.None)) { return(1); } return(0); }; } return(layoutData); }
/// <summary> /// Run a layout and an analysis algorithm if wanted. /// </summary> /// <param name="incremental">Whether to run in incremental mode, i.e. only moving new items.</param> /// <param name="clearUndo">Whether to clear the undo queue after the layout.</param> /// <param name="runAlgorithm">Whether to apply the <see cref="CurrentConfig">current analysis algorithm</see>, too.</param> /// <returns></returns> private async Task RunLayout(bool incremental, bool clearUndo, bool runAlgorithm) { // the actual organic layout var layout = new OrganicLayout { Deterministic = true, ConsiderNodeSizes = true, Scope = incremental ? Scope.MainlySubset : Scope.All, LabelingEnabled = false, PreferredEdgeLength = 100, MinimumNodeDistance = 10 }; ((ComponentLayout)layout.ComponentLayout).Style = ComponentArrangementStyles.None | ComponentArrangementStyles.ModifierNoOverlap; OrganicLayoutData layoutData = null; if (incremental && incrementalNodesMapper != null) { layoutData = new OrganicLayoutData(); layoutData.AffectedNodes.Mapper = incrementalNodesMapper; } inLayout = true; SetUiDisabled(true); // run the layout in an asynchronous, animated fashion await graphControl.MorphLayout(layout, TimeSpan.FromSeconds(0.5), layoutData); // run algorithm if (runAlgorithm) { // apply graph algorithms after layout ApplyAlgorithm(); var algorithm = algorithmComboBox.SelectedItem as Algorithm; if (algorithm != null && algorithm.DisplayName.EndsWith("Centrality")) { // since centrality changes the node sizes, node overlaps need to be removed await graphControl.MorphLayout(new OrganicRemoveOverlapsStage(), TimeSpan.FromSeconds(0.2)); } } // labeling: place labels after the layout and the analysis (which might have generated or changed labels) var labeling = new GenericLabeling { PlaceEdgeLabels = true, PlaceNodeLabels = false, Deterministic = true }; var labelingData = new LabelingData { EdgeLabelPreferredPlacement = { Delegate = label => { var preferredPlacementDescriptor = new PreferredPlacementDescriptor(); if ("Centrality".Equals(label.Tag)) { preferredPlacementDescriptor.SideOfEdge = LabelPlacements.OnEdge; } else { preferredPlacementDescriptor.SideOfEdge = LabelPlacements.RightOfEdge | LabelPlacements.LeftOfEdge; preferredPlacementDescriptor.DistanceToEdge = 5; } preferredPlacementDescriptor.Freeze(); return(preferredPlacementDescriptor); } } }; await graphControl.MorphLayout(labeling, TimeSpan.FromSeconds(0.2), labelingData); // cleanup if (clearUndo) { graphControl.Graph.GetUndoEngine().Clear(); } // clean up data provider incrementalNodesMapper.Clear(); // enable the UI's buttons ReleaseLocks(); SetUiDisabled(false); UpdateUiState(); }