Interaction logic for CommitBox.xaml
Inheritance: System.Windows.Controls.UserControl
        internal void Show(GitFileStatusTracker tracker)
        {
            this.tracker = tracker;

            loading.Visibility = Visibility.Visible;

            var dispatcher = Dispatcher.CurrentDispatcher;
            Action act = () =>
            {
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();

                try
                {
                    IList<GraphNode> commits = null;
                    string hash = null;

                    if (tracker != null && tracker.HasGitRepository)
                    {
                        this.tracker.RepositoryGraph.IsSimplified = showSimplifiedGraph;
                        commits = tracker.RepositoryGraph.Nodes;
                        hash = GetHashCode(commits);
                    }

                    bool changed = lastHash == null ? hash != null : !lastHash.Equals(hash);

                    if (changed)
                    {
                        lastHash = hash;

                        canvasContainer.Children.Clear();
                        maxX = maxY = 0;

                        if (changed && commits != null && commits.Count > 0)
                        {
                            maxX = commits.Count();
                            maxY = commits.Max(c => c.X);

                            for (int i = commits.Count() - 1; i >= 0; i--)
                            {
                                var commit = commits[i];

                                #region Add commit box

                                var box = new CommitBox();
                                box.DataContext = new
                                {
                                    Id = commit.Id,
                                    ShortId = commit.Id.Substring(0, 7),
                                    Comments = commit.Message,
                                    Author = commit.CommitterName,
                                    Date = commit.CommitDateRelative,
                                };

                                double left = GetScreenX(maxX - commit.Y);
                                double top = GetScreenY(commit.X);

                                Canvas.SetLeft(box, left);
                                Canvas.SetTop(box, top);
                                Canvas.SetZIndex(box, 10);

                                this.canvasContainer.Children.Add(box);

                                #endregion

                                #region Add Branches

                                var m = 0;
                                foreach (var name in commit.Refs.Where(r => r.Type == RefTypes.Branch || r.Type == RefTypes.HEAD))
                                {
                                    var control = new CommitHead
                                    {
                                        DataContext = new { Text = name },
                                    };

                                    Canvas.SetLeft(control, left + CommitBox.WIDTH + 4);
                                    Canvas.SetTop(control, top + m++ * 30);

                                    this.canvasContainer.Children.Add(control);
                                }
                                #endregion

                                #region Add Tags
                                m = 0;
                                foreach (var name in commit.Refs.Where(r => r.Type == RefTypes.Tag))
                                {
                                    var control = new CommitTag
                                    {
                                        DataContext = new { Text = name },
                                    };

                                    Canvas.SetLeft(control, left + m++ * 100); // TODO: get width of the control
                                    Canvas.SetTop(control, top - 24);

                                    this.canvasContainer.Children.Add(control);
                                }

                                #endregion

                                #region Add Remote Branches
                                m = 0;
                                foreach (var name in commit.Refs.Where(r => r.Type == RefTypes.RemoteBranch))
                                {
                                    var control = new CommitRemote
                                    {
                                        DataContext = new { Text = name },
                                    };

                                    Canvas.SetLeft(control, left + m++ * 100); // TODO: get width of the control
                                    Canvas.SetTop(control, top + CommitBox.HEIGHT + 4);

                                    this.canvasContainer.Children.Add(control);
                                }
                                #endregion
                            }

                            #region Add commit links

                            var links = tracker.RepositoryGraph.Links;

                            foreach (var link in links)
                            {
                                // current node
                                double x1 = link.Y1;
                                double y1 = link.X1;

                                // parent node
                                double x2 = link.Y2;
                                double y2 = link.X2;

                                bool flip = links.Any(lnk => lnk.X1 == x2 && lnk.Y2 == y2 && lnk.X1 == lnk.X2);

                                x1 = GetScreenX(maxX - x1);
                                y1 = GetScreenY(y1) + CommitBox.HEIGHT / 2;
                                x2 = GetScreenX(maxX - x2) + CommitBox.WIDTH;
                                y2 = GetScreenY(y2) + CommitBox.HEIGHT / 2;

                                if (y1 == y2)
                                {
                                    var line = new Line
                                    {
                                        Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };
                                    line.X1 = x1;
                                    line.Y1 = y1;
                                    line.X2 = x2;
                                    line.Y2 = y2;
                                    this.canvasContainer.Children.Add(line);
                                }
                                else if (y1 > y2 && !flip)
                                {
                                    var x3 = x2 - CommitBox.WIDTH / 2;
                                    var path = new System.Windows.Shapes.Path
                                    {
                                        Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };

                                    PathSegmentCollection pscollection = new PathSegmentCollection();

                                    pscollection.Add(new LineSegment(new Point(x2, y1), true));

                                    BezierSegment curve = new BezierSegment(
                                        new Point(x2, y1), new Point(x3, y1), new Point(x3, y2), true);
                                    pscollection.Add(curve);

                                    PathFigure pf = new PathFigure
                                    {
                                        StartPoint = new Point(x1, y1),
                                        Segments = pscollection,
                                    };
                                    PathFigureCollection pfcollection = new PathFigureCollection();
                                    pfcollection.Add(pf);
                                    PathGeometry pathGeometry = new PathGeometry();
                                    pathGeometry.Figures = pfcollection;
                                    path.Data = pathGeometry;

                                    this.canvasContainer.Children.Add(path);
                                }
                                else
                                {
                                    var x3 = x1 + CommitBox.WIDTH / 2;
                                    var path = new System.Windows.Shapes.Path
                                    {
                                        Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };

                                    PathSegmentCollection pscollection = new PathSegmentCollection();

                                    BezierSegment curve = new BezierSegment(
                                        new Point(x3, y1), new Point(x3, y2), new Point(x1, y2), true);
                                    pscollection.Add(curve);

                                    pscollection.Add(new LineSegment(new Point(x2, y2), true));

                                    PathFigure pf = new PathFigure
                                    {
                                        StartPoint = new Point(x3, y1),
                                        Segments = pscollection,
                                    };
                                    PathFigureCollection pfcollection = new PathFigureCollection();
                                    pfcollection.Add(pf);
                                    PathGeometry pathGeometry = new PathGeometry();
                                    pathGeometry.Figures = pfcollection;
                                    path.Data = pathGeometry;

                                    this.canvasContainer.Children.Add(path);
                                }
                            }

                            #endregion
                        }

                        AdjustCanvasSize(this.Scaler.ScaleX);
                    }

                }
                catch (Exception ex)
                {
                    Log.WriteLine("History Graph Show: {0}", ex.ToString());
                }

                loading.Visibility = Visibility.Collapsed;

                stopwatch.Stop();
                Debug.WriteLine("**** HistoryGraph Refresh: " + stopwatch.ElapsedMilliseconds);

                service.NoRefresh = false;
                service.lastTimeRefresh = DateTime.Now; //important!!

            };

            dispatcher.BeginInvoke(act, DispatcherPriority.ApplicationIdle);
        }
        internal void Show(GitFileStatusTracker tracker)
        {
            this.tracker = tracker;

            loading.Visibility = Visibility.Visible;

            var    dispatcher = Dispatcher.CurrentDispatcher;
            Action act        = () =>
            {
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();

                try
                {
                    IList <GraphNode> commits = null;
                    string            hash    = null;

                    if (tracker != null && tracker.HasGitRepository)
                    {
                        this.tracker.RepositoryGraph.IsSimplified = showSimplifiedGraph;
                        commits = tracker.RepositoryGraph.Nodes;
                        hash    = GetHashCode(commits);
                    }

                    bool changed = lastHash == null ? hash != null : !lastHash.Equals(hash);

                    if (changed)
                    {
                        lastHash = hash;

                        canvasContainer.Children.Clear();
                        maxX = maxY = 0;

                        if (changed && commits != null && commits.Count > 0)
                        {
                            maxX = commits.Count();
                            maxY = commits.Max(c => c.X);

                            for (int i = commits.Count() - 1; i >= 0; i--)
                            {
                                var commit = commits[i];

                                #region Add commit box

                                var box = new CommitBox();
                                box.DataContext = new
                                {
                                    Id       = commit.Id,
                                    ShortId  = commit.Id.Substring(0, 7),
                                    Comments = commit.Message,
                                    Author   = commit.CommitterName,
                                    Date     = commit.CommitDateRelative,
                                };

                                double left = GetScreenX(maxX - commit.Y);
                                double top  = GetScreenY(commit.X);

                                Canvas.SetLeft(box, left);
                                Canvas.SetTop(box, top);
                                Canvas.SetZIndex(box, 10);

                                this.canvasContainer.Children.Add(box);

                                #endregion

                                #region Add Branches

                                var m = 0;
                                foreach (var name in commit.Refs.Where(r => r.Type == RefTypes.Branch || r.Type == RefTypes.HEAD))
                                {
                                    var control = new CommitHead
                                    {
                                        DataContext = new { Text = name },
                                    };

                                    Canvas.SetLeft(control, left + CommitBox.WIDTH + 4);
                                    Canvas.SetTop(control, top + m++ *30);

                                    this.canvasContainer.Children.Add(control);
                                }
                                #endregion

                                #region Add Tags
                                m = 0;
                                foreach (var name in commit.Refs.Where(r => r.Type == RefTypes.Tag))
                                {
                                    var control = new CommitTag
                                    {
                                        DataContext = new { Text = name },
                                    };

                                    Canvas.SetLeft(control, left + m++ *100);  // TODO: get width of the control
                                    Canvas.SetTop(control, top - 24);

                                    this.canvasContainer.Children.Add(control);
                                }

                                #endregion

                                #region Add Remote Branches
                                m = 0;
                                foreach (var name in commit.Refs.Where(r => r.Type == RefTypes.RemoteBranch))
                                {
                                    var control = new CommitRemote
                                    {
                                        DataContext = new { Text = name },
                                    };

                                    Canvas.SetLeft(control, left + m++ *100);  // TODO: get width of the control
                                    Canvas.SetTop(control, top + CommitBox.HEIGHT + 4);

                                    this.canvasContainer.Children.Add(control);
                                }
                                #endregion
                            }

                            #region Add commit links

                            var links = tracker.RepositoryGraph.Links;

                            foreach (var link in links)
                            {
                                // current node
                                double x1 = link.Y1;
                                double y1 = link.X1;

                                // parent node
                                double x2 = link.Y2;
                                double y2 = link.X2;

                                bool flip = links.Any(lnk => lnk.X1 == x2 && lnk.Y2 == y2 && lnk.X1 == lnk.X2);

                                x1 = GetScreenX(maxX - x1);
                                y1 = GetScreenY(y1) + CommitBox.HEIGHT / 2;
                                x2 = GetScreenX(maxX - x2) + CommitBox.WIDTH;
                                y2 = GetScreenY(y2) + CommitBox.HEIGHT / 2;

                                if (y1 == y2)
                                {
                                    var line = new Line
                                    {
                                        Stroke          = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };
                                    line.X1 = x1;
                                    line.Y1 = y1;
                                    line.X2 = x2;
                                    line.Y2 = y2;
                                    this.canvasContainer.Children.Add(line);
                                }
                                else if (y1 > y2 && !flip)
                                {
                                    var x3   = x2 - CommitBox.WIDTH / 2;
                                    var path = new System.Windows.Shapes.Path
                                    {
                                        Stroke          = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };

                                    PathSegmentCollection pscollection = new PathSegmentCollection();

                                    pscollection.Add(new LineSegment(new Point(x2, y1), true));

                                    BezierSegment curve = new BezierSegment(
                                        new Point(x2, y1), new Point(x3, y1), new Point(x3, y2), true);
                                    pscollection.Add(curve);

                                    PathFigure pf = new PathFigure
                                    {
                                        StartPoint = new Point(x1, y1),
                                        Segments   = pscollection,
                                    };
                                    PathFigureCollection pfcollection = new PathFigureCollection();
                                    pfcollection.Add(pf);
                                    PathGeometry pathGeometry = new PathGeometry();
                                    pathGeometry.Figures = pfcollection;
                                    path.Data            = pathGeometry;

                                    this.canvasContainer.Children.Add(path);
                                }
                                else
                                {
                                    var x3   = x1 + CommitBox.WIDTH / 2;
                                    var path = new System.Windows.Shapes.Path
                                    {
                                        Stroke          = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };

                                    PathSegmentCollection pscollection = new PathSegmentCollection();

                                    BezierSegment curve = new BezierSegment(
                                        new Point(x3, y1), new Point(x3, y2), new Point(x1, y2), true);
                                    pscollection.Add(curve);

                                    pscollection.Add(new LineSegment(new Point(x2, y2), true));

                                    PathFigure pf = new PathFigure
                                    {
                                        StartPoint = new Point(x3, y1),
                                        Segments   = pscollection,
                                    };
                                    PathFigureCollection pfcollection = new PathFigureCollection();
                                    pfcollection.Add(pf);
                                    PathGeometry pathGeometry = new PathGeometry();
                                    pathGeometry.Figures = pfcollection;
                                    path.Data            = pathGeometry;

                                    this.canvasContainer.Children.Add(path);
                                }
                            }

                            #endregion
                        }

                        AdjustCanvasSize(this.Scaler.ScaleX);
                    }
                }
                catch (Exception ex)
                {
                    Log.WriteLine("History Graph Show: {0}", ex.ToString());
                }

                loading.Visibility = Visibility.Collapsed;

                stopwatch.Stop();
                Debug.WriteLine("**** HistoryGraph Refresh: " + stopwatch.ElapsedMilliseconds);

                service.NoRefresh       = false;
                service.lastTimeRefresh = DateTime.Now; //important!!
            };

            dispatcher.BeginInvoke(act, DispatcherPriority.ApplicationIdle);
        }
        internal void Show(GitFileStatusTracker tracker, bool scroll)
        {
            this.tracker = tracker;

            //loading.Visibility = Visibility.Visible;

            Action action = () =>
            {
                try
                {
                    IList<GraphNode> commits = null;
                    string hash = null;

                    if (tracker != null && tracker.HasGitRepository)
                    {
                        commits = tracker.RepositoryGraph.Nodes;
                        hash = GetHashCode(commits);
                    }

                    bool changed = lastHash == null ? hash != null : !lastHash.Equals(hash);

                    if (changed)
                    {
                        lastHash = hash;

                        canvasContainer.Children.Clear();
                        maxX = maxY = 0;

                        if (changed && commits != null && commits.Any())
                        {
                            maxX = commits.Count();
                            maxY = commits.Max(c => c.X);

                            for (int i = commits.Count() - 1; i >= 0; i--)
                            {
                                var commit = commits[i];

                                #region Add commit box

                                var box = new CommitBox();
                                box.DataContext = new
                                {
                                    Id = commit.Id,
                                    ShortId = commit.ShortId,
                                    Comments = commit.Message,
                                    Author = commit.AuthorName,
                                    Date = commit.AuthorDateRelative,
                                    Refs = commit.Refs
                                };

                                double left = GetScreenX(maxX - commit.Y);
                                double top = GetScreenY(commit.X);

                                Canvas.SetLeft(box, left);
                                Canvas.SetTop(box, top);
                                Canvas.SetZIndex(box, 10);

                                this.canvasContainer.Children.Add(box);

                                #endregion

                                #region Add Branches

                                var m = 0;
                                foreach (var head in commit.Refs.Where(r => r.Type == RefTypes.Branch || r.Type == RefTypes.HEAD))
                                {
                                    var control = new CommitHead
                                    {
                                        DataContext = head,
                                    };

                                    Canvas.SetLeft(control, left + CommitBox.WIDTH + 4);
                                    Canvas.SetTop(control, top + m++ * 30);

                                    this.canvasContainer.Children.Add(control);

                                }
                                #endregion

                                #region Add Tags
                                m = 0;
                                foreach (var tag in commit.Refs.Where(r => r.Type == RefTypes.Tag))
                                {
                                    var control = new CommitTag
                                    {
                                        DataContext = tag,
                                    };

                                    Canvas.SetLeft(control, left + m++ * 80); // TODO: get width of the control
                                    Canvas.SetTop(control, top - 24);

                                    this.canvasContainer.Children.Add(control);
                                }

                                #endregion

                                #region Add Remote Branches
                                m = 0;
                                foreach (var name in commit.Refs.Where(r => r.Type == RefTypes.RemoteBranch))
                                {
                                    var control = new CommitRemote
                                    {
                                        DataContext = new { Text = name },
                                    };

                                    Canvas.SetLeft(control, left + m++ * 100); // TODO: get width of the control
                                    Canvas.SetTop(control, top + CommitBox.HEIGHT + 4);

                                    this.canvasContainer.Children.Add(control);
                                }
                                #endregion
                            }

                            #region Add commit links

                            var links = tracker.RepositoryGraph.Links;

                            foreach (var link in links)
                            {
                                // current node
                                double x1 = link.Y1;
                                double y1 = link.X1;

                                // parent node
                                double x2 = link.Y2;
                                double y2 = link.X2;

                                bool flip = links.Any(lnk => lnk.X1 == x2 && lnk.Y2 == y2 && lnk.X1 == lnk.X2);

                                x1 = GetScreenX(maxX - x1);
                                y1 = GetScreenY(y1) + CommitBox.HEIGHT / 2;
                                x2 = GetScreenX(maxX - x2) + CommitBox.WIDTH;
                                y2 = GetScreenY(y2) + CommitBox.HEIGHT / 2;

                                if (y1 == y2)
                                {
                                    var line = new Line
                                    {
                                        Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };
                                    line.X1 = x1;
                                    line.Y1 = y1;
                                    line.X2 = x2;
                                    line.Y2 = y2;
                                    this.canvasContainer.Children.Add(line);
                                }
                                else if (y1 > y2 && !flip)
                                {
                                    var x3 = x2 - CommitBox.WIDTH / 2;
                                    var path = new System.Windows.Shapes.Path
                                    {
                                        Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };

                                    PathSegmentCollection pscollection = new PathSegmentCollection();

                                    pscollection.Add(new LineSegment(new Point(x2, y1), true));

                                    BezierSegment curve = new BezierSegment(
                                        new Point(x2, y1), new Point(x3, y1), new Point(x3, y2), true);
                                    pscollection.Add(curve);

                                    PathFigure pf = new PathFigure
                                    {
                                        StartPoint = new Point(x1, y1),
                                        Segments = pscollection,
                                    };
                                    PathFigureCollection pfcollection = new PathFigureCollection();
                                    pfcollection.Add(pf);
                                    PathGeometry pathGeometry = new PathGeometry();
                                    pathGeometry.Figures = pfcollection;
                                    path.Data = pathGeometry;

                                    this.canvasContainer.Children.Add(path);
                                }
                                else
                                {
                                    var x3 = x1 + CommitBox.WIDTH / 2;
                                    var path = new System.Windows.Shapes.Path
                                    {
                                        Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };

                                    PathSegmentCollection pscollection = new PathSegmentCollection();

                                    BezierSegment curve = new BezierSegment(
                                        new Point(x3, y1), new Point(x3, y2), new Point(x1, y2), true);
                                    pscollection.Add(curve);

                                    pscollection.Add(new LineSegment(new Point(x2, y2), true));

                                    PathFigure pf = new PathFigure
                                    {
                                        StartPoint = new Point(x3, y1),
                                        Segments = pscollection,
                                    };
                                    PathFigureCollection pfcollection = new PathFigureCollection();
                                    pfcollection.Add(pf);
                                    PathGeometry pathGeometry = new PathGeometry();
                                    pathGeometry.Figures = pfcollection;
                                    path.Data = pathGeometry;

                                    this.canvasContainer.Children.Add(path);
                                }
                            }

                            #endregion
                        }

                        AdjustCanvasSize();
                    }

                    if (scroll)
                    {
                        //this.Scaler.ScaleX = this.Scaler.ScaleY = 1;
                        //AdjustCanvasSize();

                        this.zoomAndPanControl.ContentScale = 1;
                        this.canvasContainer.SetValue(Canvas.LeftProperty, 0.0);
                        this.canvasContainer.SetValue(Canvas.TopProperty, 0.0);
                        this.scrollRoot.ScrollToRightEnd();
                    }
                }
                catch (Exception ex)
                {
                    Log.WriteLine("History Graph Show: {0}", ex.ToString());
                }

                //loading.Visibility = Visibility.Collapsed;

                HistoryViewCommands.GraphLoaded.Execute(null, this);
            };

            this.Dispatcher.BeginInvoke(action, DispatcherPriority.Background);
        }
        internal void Show(GitFileStatusTracker tracker, bool scroll)
        {
            this.tracker = tracker;

            //loading.Visibility = Visibility.Visible;

            Action action = () =>
            {
                try
                {
                    IList <GraphNode> commits = null;
                    string            hash    = null;

                    if (tracker != null && tracker.IsGit)
                    {
                        commits = tracker.RepositoryGraph.Nodes;
                        hash    = GetHashCode(commits);
                    }

                    bool changed = true; // lastHash == null ? hash != null : !lastHash.Equals(hash);

                    if (changed)
                    {
                        lastHash = hash;

                        canvasContainer.Children.Clear();
                        maxX = maxY = 0;

                        if (changed && commits != null && commits.Any())
                        {
                            maxX = commits.Count();
                            maxY = commits.Max(c => c.X);

                            for (int i = commits.Count() - 1; i >= 0; i--)
                            {
                                var commit = commits[i];

                                #region Add commit box

                                var box = new CommitBox();
                                box.DataContext = new
                                {
                                    Id       = commit.Id,
                                    ShortId  = commit.ShortId,
                                    Comments = commit.Message,
                                    Author   = commit.AuthorName,
                                    Date     = commit.AuthorDateRelative,
                                    Refs     = commit.Refs
                                };

                                double left = GetScreenX(maxX - commit.Y);
                                double top  = GetScreenY(commit.X);

                                Canvas.SetLeft(box, left);
                                Canvas.SetTop(box, top);
                                Canvas.SetZIndex(box, 10);

                                this.canvasContainer.Children.Add(box);

                                #endregion

                                #region Add Branches

                                var m = 0;
                                foreach (var head in commit.Refs.Where(r => r.Type == RefTypes.Branch || r.Type == RefTypes.HEAD))
                                {
                                    var control = new CommitHead
                                    {
                                        DataContext = head,
                                    };

                                    Canvas.SetLeft(control, left + CommitBox.WIDTH + 4);
                                    Canvas.SetTop(control, top + m++ *30);

                                    this.canvasContainer.Children.Add(control);
                                }
                                #endregion

                                #region Add Tags
                                m = 0;
                                foreach (var tag in commit.Refs.Where(r => r.Type == RefTypes.Tag))
                                {
                                    var control = new CommitTag
                                    {
                                        DataContext = tag,
                                    };

                                    Canvas.SetLeft(control, left + m++ *80);  // TODO: get width of the control
                                    Canvas.SetTop(control, top - 24);

                                    this.canvasContainer.Children.Add(control);
                                }

                                #endregion

                                #region Add Remote Branches
                                m = 0;
                                foreach (var name in commit.Refs.Where(r => r.Type == RefTypes.RemoteBranch))
                                {
                                    var control = new CommitRemote
                                    {
                                        DataContext = new { Text = name },
                                    };

                                    Canvas.SetLeft(control, left + m++ *100);  // TODO: get width of the control
                                    Canvas.SetTop(control, top + CommitBox.HEIGHT + 4);

                                    this.canvasContainer.Children.Add(control);
                                }
                                #endregion
                            }

                            #region Add commit links

                            var links = tracker.RepositoryGraph.Links;

                            foreach (var link in links)
                            {
                                // current node
                                double x1 = link.Y1;
                                double y1 = link.X1;

                                // parent node
                                double x2 = link.Y2;
                                double y2 = link.X2;

                                bool flip = links.Any(lnk => lnk.X1 == x2 && lnk.Y2 == y2 && lnk.X1 == lnk.X2);

                                x1 = GetScreenX(maxX - x1);
                                y1 = GetScreenY(y1) + CommitBox.HEIGHT / 2;
                                x2 = GetScreenX(maxX - x2) + CommitBox.WIDTH;
                                y2 = GetScreenY(y2) + CommitBox.HEIGHT / 2;

                                if (y1 == y2)
                                {
                                    var line = new Line
                                    {
                                        Stroke          = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };
                                    line.X1 = x1;
                                    line.Y1 = y1;
                                    line.X2 = x2;
                                    line.Y2 = y2;
                                    this.canvasContainer.Children.Add(line);
                                }
                                else if (y1 > y2 && !flip)
                                {
                                    var x3   = x2 - CommitBox.WIDTH / 2;
                                    var path = new System.Windows.Shapes.Path
                                    {
                                        Stroke          = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };

                                    PathSegmentCollection pscollection = new PathSegmentCollection();

                                    pscollection.Add(new LineSegment(new Point(x2, y1), true));

                                    BezierSegment curve = new BezierSegment(
                                        new Point(x2, y1), new Point(x3, y1), new Point(x3, y2), true);
                                    pscollection.Add(curve);

                                    PathFigure pf = new PathFigure
                                    {
                                        StartPoint = new Point(x1, y1),
                                        Segments   = pscollection,
                                    };
                                    PathFigureCollection pfcollection = new PathFigureCollection();
                                    pfcollection.Add(pf);
                                    PathGeometry pathGeometry = new PathGeometry();
                                    pathGeometry.Figures = pfcollection;
                                    path.Data            = pathGeometry;

                                    this.canvasContainer.Children.Add(path);
                                }
                                else
                                {
                                    var x3   = x1 + CommitBox.WIDTH / 2;
                                    var path = new System.Windows.Shapes.Path
                                    {
                                        Stroke          = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };

                                    PathSegmentCollection pscollection = new PathSegmentCollection();

                                    BezierSegment curve = new BezierSegment(
                                        new Point(x3, y1), new Point(x3, y2), new Point(x1, y2), true);
                                    pscollection.Add(curve);

                                    pscollection.Add(new LineSegment(new Point(x2, y2), true));

                                    PathFigure pf = new PathFigure
                                    {
                                        StartPoint = new Point(x3, y1),
                                        Segments   = pscollection,
                                    };
                                    PathFigureCollection pfcollection = new PathFigureCollection();
                                    pfcollection.Add(pf);
                                    PathGeometry pathGeometry = new PathGeometry();
                                    pathGeometry.Figures = pfcollection;
                                    path.Data            = pathGeometry;

                                    this.canvasContainer.Children.Add(path);
                                }
                            }

                            #endregion
                        }

                        AdjustCanvasSize();
                    }

                    if (scroll)
                    {
                        //this.Scaler.ScaleX = this.Scaler.ScaleY = 1;
                        //AdjustCanvasSize();

                        this.zoomAndPanControl.ContentScale = 1;
                        this.canvasContainer.SetValue(Canvas.LeftProperty, 0.0);
                        this.canvasContainer.SetValue(Canvas.TopProperty, 0.0);
                        this.scrollRoot.ScrollToRightEnd();
                    }
                }
                catch (Exception ex)
                {
                    Log.WriteLine("History Graph Show: {0}", ex.ToString());
                }

                HistoryViewCommands.GraphLoaded.Execute(null, this);
            };

            this.Dispatcher.BeginInvoke(action, DispatcherPriority.Background);
        }
        internal void Show(GitFileStatusTracker tracker)
        {
            canvasContainer.Children.Clear();

            this.tracker = tracker;
            if (tracker == null) return;

            loading.Visibility = Visibility.Visible;
            var dispatcher = Dispatcher.CurrentDispatcher;

            Action act = () =>
            {
                this.tracker.RepositoryGraph.IsSimplified = showSimplifiedGraph;

                var commits = tracker.RepositoryGraph.Nodes;
                if (commits.Count <= 0) return;

                maxX = commits.Count();
                maxY = commits.Max(c => c.X);

                for (int i = commits.Count() - 1; i >= 0; i--)
                {
                    var commit = commits[i];

                    #region Add commit box

                    var box = new CommitBox();
                    box.DataContext = new
                    {
                        Id = commit.Id,
                        ShortId = commit.Id.Substring(0, 5),
                        Comments = commit.Message,
                        Author = commit.CommitterName,
                        Date = commit.CommitDateRelative,
                    };

                    double left = GetScreenX(maxX - commit.Y);
                    double top = GetScreenY(commit.X);

                    Canvas.SetLeft(box, left);
                    Canvas.SetTop(box, top);
                    Canvas.SetZIndex(box, 10);

                    this.canvasContainer.Children.Add(box);

                    #endregion

                    #region Add Branches

                    var m = 0;
                    foreach (var name in commit.Refs.Where(r=> r.Type == RefTypes.Branch || r.Type == RefTypes.HEAD))
                    {
                        var control = new CommitHead
                        {
                            DataContext = new { Text = name },
                        };

                        Canvas.SetLeft(control, left + CommitBox.WIDTH + 4);
                        Canvas.SetTop(control, top + m++ * 30);

                        this.canvasContainer.Children.Add(control);
                    }
                    #endregion

                    #region Add Tags
                    m = 0;
                    foreach (var name in commit.Refs.Where(r => r.Type == RefTypes.Tag))
                    {
                        var control = new CommitTag
                        {
                            DataContext = new { Text = name },
                        };

                        Canvas.SetLeft(control, left + m++ * 100); // TODO: get width of the control
                        Canvas.SetTop(control, top - 24);

                        this.canvasContainer.Children.Add(control);
                    }

                    #endregion

                    #region Add Remote Branches
                    m = 0;
                    foreach (var name in commit.Refs.Where(r => r.Type == RefTypes.RemoteBranch))
                    {
                        var control = new CommitRemote
                        {
                            DataContext = new { Text = name },
                        };

                        Canvas.SetLeft(control, left + m++ * 100); // TODO: get width of the control
                        Canvas.SetTop(control, top + CommitBox.HEIGHT + 4);

                        this.canvasContainer.Children.Add(control);
                    }
                    #endregion
                }

                #region Add commit links

                var links = tracker.RepositoryGraph.Links;

                foreach (var link in links)
                {
                    // current node
                    double x1 = link.Y1;
                    double y1 = link.X1;

                    // parent node
                    double x2 = link.Y2;
                    double y2 = link.X2;

                    bool flip = links.Any(lnk => lnk.X1 == x2 && lnk.Y2 == y2 && lnk.X1 == lnk.X2);

                    x1 = GetScreenX(maxX - x1);
                    y1 = GetScreenY(y1) + CommitBox.HEIGHT / 2;
                    x2 = GetScreenX(maxX - x2) + CommitBox.WIDTH;
                    y2 = GetScreenY(y2) + CommitBox.HEIGHT / 2;

                    if (y1==y2)
                    {
                        var line = new Line
                        {
                            Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                            StrokeThickness = 4,
                        };
                        line.X1 = x1;
                        line.Y1 = y1;
                        line.X2 = x2;
                        line.Y2 = y2;
                        this.canvasContainer.Children.Add(line);
                    }
                    else if (y1>y2 && !flip)
                    {
                        var x3 = x2 - CommitBox.WIDTH / 2;
                        var path = new Path
                        {
                            Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                            StrokeThickness = 4,
                        };

                        PathSegmentCollection pscollection = new PathSegmentCollection();

                        pscollection.Add(new LineSegment(new Point(x2, y1), true));

                        BezierSegment curve = new BezierSegment(
                            new Point(x2, y1), new Point(x3, y1), new Point(x3, y2), true);
                        pscollection.Add(curve);

                        PathFigure pf = new PathFigure
                        {
                            StartPoint = new Point(x1, y1),
                            Segments = pscollection,
                        };
                        PathFigureCollection pfcollection = new PathFigureCollection();
                        pfcollection.Add(pf);
                        PathGeometry pathGeometry = new PathGeometry();
                        pathGeometry.Figures = pfcollection;
                        path.Data = pathGeometry;

                        this.canvasContainer.Children.Add(path);
                    }
                    else
                    {
                        var x3 = x1 + CommitBox.WIDTH / 2;
                        var path = new Path
                        {
                            Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                            StrokeThickness = 4,
                        };

                        PathSegmentCollection pscollection = new PathSegmentCollection();

                        BezierSegment curve = new BezierSegment(
                            new Point(x3, y1), new Point(x3, y2), new Point(x1, y2), true);
                        pscollection.Add(curve);

                        pscollection.Add(new LineSegment(new Point(x2, y2), true));

                        PathFigure pf = new PathFigure
                        {
                            StartPoint = new Point(x3, y1),
                            Segments = pscollection,
                        };
                        PathFigureCollection pfcollection = new PathFigureCollection();
                        pfcollection.Add(pf);
                        PathGeometry pathGeometry = new PathGeometry();
                        pathGeometry.Figures = pfcollection;
                        path.Data = pathGeometry;

                        this.canvasContainer.Children.Add(path);
                    }
                }

                #endregion

                AdjustCanvasSize();

                this.scrollRoot.ScrollToRightEnd();

                loading.Visibility = Visibility.Collapsed;
            };
            dispatcher.BeginInvoke(act, DispatcherPriority.ApplicationIdle);
        }