private MultiStageLayout ConfigureARRouter()
        {
            var ar = new AspectRatioTreeLayout();

            CanvasControl cv = Context.Lookup <CanvasControl>();

            if (cv != null)
            {
                var size = cv.InnerSize;
                if ((bool)Handler.GetValue(AR, USE_VIEW_ASPECT_RATIO))
                {
                    ar.AspectRatio = size.Width / size.Height;
                }
                else
                {
                    ar.AspectRatio = (double)Handler.GetValue(AR, ASPECT_RATIO);
                }
            }

            ar.HorizontalDistance = (int)Handler.GetValue(AR, HORIZONTAL_SPACE);
            ar.VerticalDistance   = (int)Handler.GetValue(AR, VERTICAL_SPACE);
            ar.BendDistance       = (int)Handler.GetValue(AR, BEND_DISTANCE);

            DataProviderAdapter dp = new ARRoutingDataProviderAdapter(this);

            CurrentLayoutGraph.AddDataProvider(AspectRatioTreeLayout.SubtreeRoutingPolicyDpKey, dp);

            return(ar);
        }
        ///<inheritdoc/>
        protected override void SetupHandler()
        {
            OptionGroup generalGroup = Handler.AddGroup(GENERAL);

            generalGroup.AddList(LAYOUT_STYLE, enumStyle, DIRECTED);
            IOptionItem       allowNonTreeItem = generalGroup.AddBool(ALLOW_NON_TREE_EDGES, true);
            IOptionItem       nonTreeStyleItem = generalGroup.AddList(ROUTING_STYLE_FOR_NON_TREE_EDGES, enumRoute, ROUTE_ORTHOGONAL);
            ConstraintManager cm = new ConstraintManager(Handler);

            cm.SetEnabledOnValueEquals(allowNonTreeItem, true, nonTreeStyleItem);

            generalGroup.AddBool(ACT_ON_SELECTION_ONLY, false);
            var bundlingStrength = generalGroup.AddDouble(EDGE_BUNDLING_STRENGTH, 0.99, 0, 1);

            cm.SetEnabledOnValueEquals(nonTreeStyleItem, ROUTE_BUNDLED, bundlingStrength);

            ClassicTreeLayout treeLayout    = new ClassicTreeLayout();
            OptionGroup       directedGroup = Handler.AddGroup(DIRECTED);

            directedGroup.AddInt(MINIMAL_NODE_DISTANCE, (int)treeLayout.MinimumNodeDistance, 1, int.MaxValue);
            directedGroup.AddInt(MINIMAL_LAYER_DISTANCE, (int)treeLayout.MinimumLayerDistance, 10, int.MaxValue);
            directedGroup.AddList(ORIENTATION, enumOrient.Keys, TOP_TO_BOTTOM);
            directedGroup.AddList(PORT_STYLE, enumPortStyle.Keys, NODE_CENTER_PORTS);

            directedGroup.AddBool(INTEGRATED_NODE_LABELING, false);
            directedGroup.AddBool(INTEGRATED_EDGE_LABELING, false);

            IOptionItem edgeRoutingOption  = directedGroup.AddBool(ORTHOGONAL_EDGE_ROUTING, false);
            IOptionItem busAlignmentOption = directedGroup.AddDouble(BUS_ALIGNMENT, 0.5, 0, 1);

            directedGroup.AddDouble(VERTICAL_ALIGNMENT, 0.5, 0, 1);
            var childPolicyItem    = directedGroup.AddList(CHILD_PLACEMENT_POLICY, childPlacementPolicies.Keys, SIBLINGS_ON_SAME_LAYER);
            var globalLayeringItem = directedGroup.AddBool(ENFORCE_GLOBAL_LAYERING, false);

            cm.SetEnabledOnCondition(ConstraintManager.LogicalCondition.And(cm.CreateValueEqualsCondition(edgeRoutingOption, true),
                                                                            ConstraintManager.LogicalCondition.Or(cm.CreateValueEqualsCondition(globalLayeringItem, true),
                                                                                                                  cm.CreateValueEqualsCondition(childPolicyItem, ALL_LEAVES_ON_SAME_LAYER))),
                                     busAlignmentOption);

            var         ar      = new AspectRatioTreeLayout();
            OptionGroup arGroup = Handler.AddGroup(AR);

            arGroup.AddInt(HORIZONTAL_SPACE, (int)ar.HorizontalDistance);
            arGroup.AddInt(VERTICAL_SPACE, (int)ar.VerticalDistance);
            arGroup.AddInt(BEND_DISTANCE, (int)ar.BendDistance);
            IOptionItem ratioItem   = arGroup.AddDouble(ASPECT_RATIO, ar.AspectRatio);
            IOptionItem useViewItem = arGroup.AddBool(USE_VIEW_ASPECT_RATIO, true);

            cm.SetEnabledOnValueEquals(useViewItem, false, ratioItem);
        }
        /// <summary>
        /// Does an animated tree layout of the graph displayed by a graph control guided by the aspect ratio
        /// of the graph control.
        /// </summary>
        /// <param name="graphControl">the graph control</param>
        public static async Task DoLayout(GraphControl graphControl)
        {
            if (graphControl == null || graphControl.Graph == null)
            {
                return;
            }
            var layout = new AspectRatioTreeLayout();

            System.Windows.Size size = graphControl.InnerSize;
            double ratio             = size.Width / (1.0 * size.Height);

            layout.AspectRatio = ratio;
            ((ComponentLayout)layout.ComponentLayout).PreferredSize =
                new YDimension(graphControl.InnerSize.Width, graphControl.InnerSize.Height);

            await graphControl.MorphLayout(layout, TimeSpan.FromMilliseconds(500), null);
        }