// Public methods
        //
        public T Add <T>(T element, bool addToUndoRedo) where T : IGraphElement
        {
            System.Action redo = () =>
            {
                if (element is IVertex v)
                {
                    Execute.OnUIThread(() => ObservableVertices.Add(v));
                }
                else if (element is IEdge e)
                {
                    Execute.OnUIThread(() => ObservableEdges.Add(e));
                }
            };
            System.Action undo = () =>
            {
                Remove(element, false);
            };

            if (addToUndoRedo)
            {
                UndoRedoManager.Instance.AddAndExecute(new SimpleOperation(redo, undo));
            }
            else
            {
                redo();
            }
            return(element);
        }
        public IEdge AddEdge(IVertex source, IVertex target, bool isDirected, bool makeNotDirectedIfreversedExisted = false)
        {
            if (source == target)
            {
                return(null);
            }

            var existingEdge = ObservableEdges.FirstOrDefault(x => x.Source == source && x.Target == target);

            if (existingEdge == null)
            {
                var reversedEdge = ObservableEdges.FirstOrDefault(x => x.Source == target && x.Target == source);
                if (reversedEdge != null)
                {
                    if (makeNotDirectedIfreversedExisted && reversedEdge.IsDirected)
                    {
                        reversedEdge.IsDirected = false;
                        return(reversedEdge);
                    }
                    return(reversedEdge);
                }

                var newEdge = new Edge(source, target, isDirected);
                return(Add(newEdge, true));
            }
            return(null);
        }
        public void Remove(IGraphElement element, bool useUndoRedo = true)
        {
            if (element is IVertex)
            {
                var          vertex = element as IVertex;
                List <IEdge> edges  = null;

                System.Action redo = () =>
                {
                    Execute.OnUIThread(() => ObservableVertices.Remove(vertex));
                    edges = ObservableEdges.Where(x => x.Source == vertex || x.Target == vertex)
                            .ToList();
                    edges.ForEach(x => ObservableEdges.Remove(x));
                };
                System.Action undo = () =>
                {
                    AddVertex(vertex);
                    edges.ForEach(x => Add(x, false));
                };

                if (useUndoRedo)
                {
                    UndoRedoManager.Instance.AddAndExecute(new SimpleOperation(redo, undo));
                }
                else
                {
                    redo();
                }
            }
            else if (element is IEdge)
            {
                var           edge = element as IEdge;
                System.Action redo = () =>
                {
                    Execute.OnUIThread(() => ObservableEdges.Remove(edge));
                };
                System.Action undo = () =>
                {
                    Add(edge, false);
                };

                if (useUndoRedo)
                {
                    UndoRedoManager.Instance.AddAndExecute(new SimpleOperation(redo, undo));
                }
                else
                {
                    redo();
                }
            }
        }
 public void Clear()
 {
     Execute.OnUIThread(() => ObservableEdges.Clear());
     Execute.OnUIThread(() => ObservableVertices.Clear());
     UndoRedoManager.Instance.Clear();
 }