/// <summary>
        /// Gets all the pairs of shapes that are connected by a connector
        /// </summary>
        /// <param name="page"></param>
        /// <returns></returns>
        private static List <ConnectorEdge> _get_directed_edges_raw(IVisio.Page page)
        {
            if (page == null)
            {
                throw new System.ArgumentNullException(nameof(page));
            }

            var page_connects = page.Connects;
            var connects      = page_connects.ToList();

            var edges = new List <ConnectorEdge>();

            IVisio.Shape old_connect_shape = null;
            IVisio.Shape fromsheet         = null;

            foreach (var connect in connects)
            {
                var current_connect_shape = connect.FromSheet;

                if (current_connect_shape != old_connect_shape)
                {
                    // the currect connector is NOT same as the one we stored previously
                    // this means the previous connector is connected to only one shape (not two).
                    // So skip the previos connector and start remembering from the current connector
                    old_connect_shape = current_connect_shape;
                    fromsheet         = connect.ToSheet;
                }
                else
                {
                    // the currect connector is the same as the one we stored previously
                    // this means we have enountered it twice which means it connects two
                    // shapes and is thus an edge
                    var undirected_edge = new ConnectorEdge(current_connect_shape, fromsheet, connect.ToSheet);
                    edges.Add(undirected_edge);
                }
            }

            return(edges);
        }
        /// <summary>
        /// Returns all the directed,connected pairs of shapes in the  page
        /// </summary>
        /// <param name="page"></param>
        /// <param name="flag"></param>
        /// <returns></returns>
        public static List <ConnectorEdge> GetDirectedEdges(
            IVisio.Page page,
            ConnectorHandling flag)
        {
            if (page == null)
            {
                throw new System.ArgumentNullException(nameof(page));
            }

            var edges = ConnectionAnalyzer._get_directed_edges_raw(page);

            if (flag.DirectionSource == DirectionSource.UseConnectionOrder)
            {
                return(edges);
            }

            // At this point we know we need to analyze the connetor arrows to produce the correct results

            var connnector_ids = edges.Select(e => e.Connector.ID).ToList();

            // Get the arrows for each connector
            var src_beginarrow = ShapeSheet.SrcConstants.LineBeginArrow;
            var src_endarrow   = ShapeSheet.SrcConstants.LineEndArrow;

            var query          = new CellQuery();
            var col_beginarrow = query.Columns.Add(src_beginarrow, nameof(ShapeSheet.SrcConstants.LineBeginArrow));
            var col_endarrow   = query.Columns.Add(src_endarrow, nameof(ShapeSheet.SrcConstants.LineEndArrow));

            var arrow_table = query.GetResults <int>(page, connnector_ids);

            var directed_edges = new List <ConnectorEdge>();

            int connector_index = 0;

            foreach (var e in edges)
            {
                int beginarrow = arrow_table[connector_index][col_beginarrow];
                int endarrow   = arrow_table[connector_index][col_endarrow];

                if ((beginarrow < 1) && (endarrow < 1))
                {
                    // the line has no arrows
                    if (flag.NoArrowsHandling == NoArrowsHandling.TreatEdgeAsBidirectional)
                    {
                        // in this case treat the connector as pointing in both directions
                        var de1 = new ConnectorEdge(e.Connector, e.To, e.From);
                        var de2 = new ConnectorEdge(e.Connector, e.From, e.To);
                        directed_edges.Add(de1);
                        directed_edges.Add(de2);
                    }
                    else if (flag.NoArrowsHandling == NoArrowsHandling.ExcludeEdge)
                    {
                        // in this case ignore the connector completely
                    }
                    else
                    {
                        throw new System.ArgumentOutOfRangeException(nameof(flag));
                    }
                }
                else
                {
                    // The connector has either a from-arrow, a to-arrow, or both

                    // handle if it has a from arrow
                    if (beginarrow > 0)
                    {
                        var de = new ConnectorEdge(e.Connector, e.To, e.From);
                        directed_edges.Add(de);
                    }

                    // handle if it has a to arrow
                    if (endarrow > 0)
                    {
                        var de = new ConnectorEdge(e.Connector, e.From, e.To);
                        directed_edges.Add(de);
                    }
                }

                connector_index++;
            }

            return(directed_edges);
        }