Example #1
0
        private void UpdateDiffDimensions(DiffViewModel diffViewModel, HunkRangeInfo hunkRangeInfo)
        {
            if (TextView.IsClosed)
            {
                return;
            }

            var startLineNumber = hunkRangeInfo.NewHunkRange.StartingLineNumber;
            var endLineNumber   = startLineNumber + hunkRangeInfo.NewHunkRange.NumberOfLines - 1;

            var snapshot = TextView.TextBuffer.CurrentSnapshot;

            if (startLineNumber < 0 ||
                startLineNumber >= snapshot.LineCount ||
                endLineNumber < 0 ||
                endLineNumber >= snapshot.LineCount)
            {
                return;
            }

            var startLine = snapshot.GetLineFromLineNumber(startLineNumber);
            var endLine   = snapshot.GetLineFromLineNumber(endLineNumber);

            if (startLine == null || endLine == null)
            {
                return;
            }

            var mapTop    = _scrollBar.Map.GetCoordinateAtBufferPosition(startLine.Start) - 0.5;
            var mapBottom = _scrollBar.Map.GetCoordinateAtBufferPosition(endLine.End) + 0.5;

            diffViewModel.Top    = Math.Round(_scrollBar.GetYCoordinateOfScrollMapPosition(mapTop)) - 2.0;
            diffViewModel.Height = Math.Round(_scrollBar.GetYCoordinateOfScrollMapPosition(mapBottom)) - diffViewModel.Top + 2.0;
        }
        public static Difference EmitChange(int leftStart, int leftEnd, int rightStart, int rightEnd,
                                            int leftDiffStart, int leftDiffEnd, int rightDiffStart, int rightDiffEnd,
                                            HunkRangeInfo hunk)
        {
            var diff = new Difference()
            {
                LeftStartingLineNumber  = hunk.OriginalHunkRange.StartingLineNumber,
                RightStartingLineNumber = hunk.NewHunkRange.StartingLineNumber,
                DifferenceType          = DifferenceType.Change,
                Left = new Span()
                {
                    Start     = hunk.OriginalHunkRange.StartingLineNumber + leftStart,
                    Length    = leftEnd - leftStart,
                    End       = hunk.OriginalHunkRange.StartingLineNumber + leftEnd,
                    TextLines = hunk.DiffLines.GetRange(leftDiffStart, leftDiffEnd - leftDiffStart + 1),
                    DiffStart = leftDiffStart,
                    DiffEnd   = leftDiffEnd
                },
                Right = new Span()
                {
                    Start     = rightStart + hunk.NewHunkRange.StartingLineNumber,
                    Length    = rightEnd - rightStart,
                    End       = rightEnd + hunk.NewHunkRange.StartingLineNumber,
                    TextLines = hunk.DiffLines.GetRange(rightDiffStart, rightDiffEnd - rightDiffStart + 1),
                    DiffStart = rightDiffStart,
                    DiffEnd   = rightDiffEnd
                }
            };

            return(diff);
        }
        // Difference based on Visual Studio's Difference structure.
        // http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.text.differencing.difference.aspx
        // A span can be 0-length:
        // http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.text.span.aspx
        // This structure represents an immutable integer interval that describes a range of values,
        // from Start to End. It is closed on the left and open on the right: [Start .. End).

        public static Difference EmitNew(int leftStart, int leftEnd, int rightStart, int rightEnd,
                                         int rightDiffStart, int rightDiffEnd,
                                         HunkRangeInfo hunk)
        {
            return(new Difference()
            {
                LeftStartingLineNumber = hunk.OriginalHunkRange.StartingLineNumber,
                RightStartingLineNumber = hunk.NewHunkRange.StartingLineNumber,
                DifferenceType = DifferenceType.Add,
                Left = new Span()
                {
                    Start = hunk.OriginalHunkRange.StartingLineNumber + leftStart,
                    Length = 0, // Zero-length
                    End = hunk.OriginalHunkRange.StartingLineNumber + leftEnd
                },
                Right = new Span()
                {
                    Start = rightStart + hunk.NewHunkRange.StartingLineNumber,
                    Length = rightEnd - rightStart,
                    End = rightEnd + hunk.NewHunkRange.StartingLineNumber,
                    TextLines = hunk.DiffLines.GetRange(rightDiffStart, rightDiffEnd - rightDiffStart + 1),
                    DiffStart = rightDiffStart,
                    DiffEnd = rightDiffEnd
                }
            });
        }
Example #4
0
        protected DiffViewModel(HunkRangeInfo hunkRangeInfo, IMarginCore marginCore, Action <DiffViewModel, HunkRangeInfo> updateDiffDimensions)
        {
            HunkRangeInfo         = hunkRangeInfo;
            MarginCore            = marginCore;
            _updateDiffDimensions = updateDiffDimensions;

            MarginCore.BrushesChanged += HandleBrushesChanged;
        }
Example #5
0
        public bool RollBack(HunkRangeInfo hunkRangeInfo)
        {
            if (hunkRangeInfo.SuppressRollback)
            {
                return(false);
            }

            var snapshot = _textView.TextSnapshot;

            if (snapshot != snapshot.TextBuffer.CurrentSnapshot)
            {
                return(false);
            }

            using (var edit = snapshot.TextBuffer.CreateEdit())
            {
                Span newSpan;
                if (hunkRangeInfo.IsDeletion)
                {
                    var startLine = snapshot.GetLineFromLineNumber(hunkRangeInfo.NewHunkRange.StartingLineNumber + 1);
                    newSpan = new Span(startLine.Start.Position, 0);
                }
                else
                {
                    var startLine = snapshot.GetLineFromLineNumber(hunkRangeInfo.NewHunkRange.StartingLineNumber);
                    var endLine   = snapshot.GetLineFromLineNumber(hunkRangeInfo.NewHunkRange.StartingLineNumber + hunkRangeInfo.NewHunkRange.NumberOfLines - 1);
                    newSpan = Span.FromBounds(startLine.Start.Position, endLine.EndIncludingLineBreak.Position);
                }

                if (hunkRangeInfo.IsAddition)
                {
                    var startLine = snapshot.GetLineFromLineNumber(hunkRangeInfo.NewHunkRange.StartingLineNumber);
                    var endLine   = snapshot.GetLineFromLineNumber(hunkRangeInfo.NewHunkRange.StartingLineNumber + hunkRangeInfo.NewHunkRange.NumberOfLines - 1);
                    edit.Delete(Span.FromBounds(startLine.Start.Position, endLine.EndIncludingLineBreak.Position));
                }
                else
                {
                    var lineBreak = snapshot.GetLineFromLineNumber(0).GetLineBreakText();
                    if (String.IsNullOrEmpty(lineBreak))
                    {
                        lineBreak = Environment.NewLine;
                    }

                    var originalText = String.Join(lineBreak, hunkRangeInfo.OriginalText);
                    if (hunkRangeInfo.NewHunkRange.StartingLineNumber + hunkRangeInfo.NewHunkRange.NumberOfLines != snapshot.LineCount)
                    {
                        originalText += lineBreak;
                    }

                    edit.Replace(newSpan, originalText);
                }

                edit.Apply();

                return(true);
            }
        }
Example #6
0
        internal EditorDiffViewModel(HunkRangeInfo hunkRangeInfo, IMarginCore marginCore, Action <DiffViewModel, HunkRangeInfo> updateDiffDimensions)
            : base(hunkRangeInfo, marginCore, updateDiffDimensions)
        {
            ShowPopup = false;

            DiffText = GetDiffText();

            IsDiffTextVisible = GetIsDiffTextVisible();

            UpdateDimensions();
        }
        public void IsDeletion_3DeletedLines_ExpectTrue()
        {
            //Arrange
            var hunkRangeInfo = new HunkRangeInfo(new HunkRange("-7,3", _contextLines), new HunkRange("+6,0", _contextLines), new List <string> {
                "-using Microsoft.VisualStudio.Shell;", "-using Microsoft.VisualStudio.Text;", "-using Microsoft.VisualStudio.Text.Editor;"
            }.ToArray());

            //Act
            var isDeletion = hunkRangeInfo.IsDeletion;

            //Assert
            isDeletion.ShouldBe(true);
        }
        public void IsAddition_NotAllDiffLinesStartsWithPlusSign_ExpectedFalse()
        {
            //Arrange
            var hunkRangeInfo = new HunkRangeInfo(new HunkRange("-41,0", _contextLines), new HunkRange("+42,20", _contextLines), new List <string> {
                "+ ", "- "
            }.ToArray());

            //Act
            bool isAddition = hunkRangeInfo.IsAddition;

            //Assert
            isAddition.ShouldBe(false);
        }
        public void IsModification_DiffLinesStartsWithPlusSignAndWithMinus_ExpectedTrue()
        {
            //Arrange
            var hunkRangeInfo = new HunkRangeInfo(new HunkRange("-41,0", _contextLines), new HunkRange("+42,20", _contextLines), new List <string> {
                "+ ", "- "
            }.ToArray());

            //Act
            bool isModification = hunkRangeInfo.IsModification;

            //Assert
            isModification.ShouldBe(true);
        }
        public void OriginalText_1NewLineAnd1OriginalLineWithLeadingSpaces_ExpectedOriginalText()
        {
            //Arrange
            var hunkRangeInfo = new HunkRangeInfo(new HunkRange("-41,0", _contextLines), new HunkRange("+42,20", _contextLines), new List <string> {
                "+ New Text", "-    Original Text"
            }.ToArray());

            //Act
            string originalText = hunkRangeInfo.OriginalText[0];

            //Assert
            originalText.ShouldBe("    Original Text");
        }
        public void OriginalText_1NewLineAnd1OriginalLineWithLeadingSpacesAndInvertedOrder_ExpectedOriginalText()
        {
            //Arrange
            var hunkRangeInfo = new HunkRangeInfo(new HunkRange("-18", _contextLines), new HunkRange("+18", _contextLines), new List <string> {
                "-            it++; // this is just a comment", "+            it--;"
            }.ToArray());

            //Act
            var originalText = hunkRangeInfo.OriginalText;

            //Assert
            originalText[0].ShouldBe("            it++; // this is just a comment");
        }
Example #12
0
        internal DiffViewModel(GitDiffMargin margin, HunkRangeInfo hunkRangeInfo, IWpfTextView textView, IGitCommands gitCommands)
        {
            _margin                 = margin;
            _hunkRangeInfo          = hunkRangeInfo;
            _textView               = textView;
            _gitCommands            = gitCommands;
            _margin.BrushesChanged += HandleBrushesChanged;

            ShowPopup = false;

            SetDisplayProperties();

            DiffText = GetDiffText();

            IsDiffTextVisible = GetIsDiffTextVisible();
        }
        public DiffViewModel(DiffMargin margin, HunkRangeInfo hunkRangeInfo, IWpfTextView textView)
        {
            _margin = margin;
            _hunkRangeInfo = hunkRangeInfo;
            _textView = textView;
            _margin.BrushesChanged += HandleBrushesChanged;

            _copyOldTextCommand = new RelayCommand(CopyOldText, CopyOldTextCanExecute);
            _showPopUpCommand = new RelayCommand(ShowPopUp);
            _rollbackCommand = new RelayCommand(Rollback, RollbackCanExecute);

            ShowPopup = false;

            SetDisplayProperties(false, null);

            DiffText = GetDiffText();

            IsDiffTextVisible = GetIsDiffTextVisible();
        }
Example #14
0
        public DiffViewModel(DiffMargin margin, HunkRangeInfo hunkRangeInfo, IWpfTextView textView)
        {
            _margin                 = margin;
            _hunkRangeInfo          = hunkRangeInfo;
            _textView               = textView;
            _margin.BrushesChanged += HandleBrushesChanged;

            _copyOldTextCommand = new RelayCommand(CopyOldText, CopyOldTextCanExecute);
            _showPopUpCommand   = new RelayCommand(ShowPopUp);
            _rollbackCommand    = new RelayCommand(Rollback, RollbackCanExecute);

            ShowPopup = false;

            SetDisplayProperties(false, null);

            DiffText = GetDiffText();

            IsDiffTextVisible = GetIsDiffTextVisible();
        }
        private void UpdateDiffDimensions(DiffViewModel diffViewModel, HunkRangeInfo hunkRangeInfo)
        {
            if (TextView.IsClosed)
            {
                return;
            }

            bool?visible;

            if (diffViewModel.IsDeletion)
            {
                visible = UpdateDeletedDiffDimensions(diffViewModel, hunkRangeInfo);
            }
            else
            {
                visible = UpdateNormalDiffDimensions(diffViewModel, hunkRangeInfo);
            }

            if (visible.HasValue)
            {
                diffViewModel.IsVisible = visible.Value;
            }
        }
        private IEnumerable <Linegram> SalientLines(int maxSize, HunkRangeInfo chunk)
        {
            var salient = chunk.DiffLines
                          .Select(line =>
                                  new
            {
                Salience = reader.LineSalience(2, line),
                Line     = line,
            }
                                  )
                          .OrderBy(salientLine => 1 - salientLine.Salience)
                          .ToList();

            //chunk.NewHunkRange;

            var lines = salient
                        .Take(maxSize)
                        .Select(salientLine => new Linegram()
            {
                Line = salientLine.Line
            });

            return(lines);
        }
Example #17
0
        private void UpdateDimensions(bool approximate, TextViewLayoutChangedEventArgs e)
        {
            if (_reverted)
            {
                return;
            }

            if (approximate)
            {
                // TODO: we might be able to improve support for items initially off screen
                if (!IsVisible)
                {
                    return;
                }

                if (e.OldViewState.EditSnapshot != e.NewViewState.EditSnapshot)
                {
                    // TODO: handle to prevent flickering during edits
                    IsVisible = false;
                    return;
                }

                double shift = e.NewViewState.ViewportTop - e.OldViewState.ViewportTop;
                this.Top -= shift;
                // TODO: update height for blocks which were partially off-screen
                return;
            }

            ITextSnapshot snapshot      = _textView.TextBuffer.CurrentSnapshot;
            HunkRangeInfo hunkRangeInfo = _hunkRangeInfo.TranslateTo(snapshot);

            int startLineNumber = hunkRangeInfo.NewHunkRange.StartingLineNumber;
            int endLineNumber   = startLineNumber + hunkRangeInfo.NewHunkRange.NumberOfLines - 1;

            if (startLineNumber < 0 ||
                startLineNumber >= snapshot.LineCount ||
                endLineNumber < 0 ||
                endLineNumber >= snapshot.LineCount)
            {
                IsVisible = false;
                return;
            }

            ITextSnapshotLine startLine = _textView.TextSnapshot.GetLineFromLineNumber(startLineNumber);
            ITextSnapshotLine endLine   = _textView.TextSnapshot.GetLineFromLineNumber(endLineNumber);

            if (startLine != null && endLine != null)
            {
                if (endLine.LineNumber < startLine.LineNumber)
                {
                    SnapshotSpan span = new SnapshotSpan(endLine.Start, startLine.End);
                    if (!_textView.TextViewLines.FormattedSpan.IntersectsWith(span))
                    {
                        IsVisible = false;
                        return;
                    }
                }
                else
                {
                    SnapshotSpan span = new SnapshotSpan(startLine.Start, endLine.End);
                    if (!_textView.TextViewLines.FormattedSpan.IntersectsWith(span))
                    {
                        IsVisible = false;
                        return;
                    }
                }

                IWpfTextViewLine startLineView = _textView.GetTextViewLineContainingBufferPosition(startLine.Start);
                IWpfTextViewLine endLineView   = _textView.GetTextViewLineContainingBufferPosition(endLine.Start);
                if (startLineView == null || endLineView == null)
                {
                    IsVisible = false;
                    return;
                }

                if (_textView.TextViewLines.LastVisibleLine.EndIncludingLineBreak < startLineView.Start ||
                    _textView.TextViewLines.FirstVisibleLine.Start > endLineView.EndIncludingLineBreak)
                {
                    IsVisible = false;
                    return;
                }

                double startTop;
                switch (startLineView.VisibilityState)
                {
                case VisibilityState.FullyVisible:
                    startTop = startLineView.Top - _textView.ViewportTop;
                    break;

                case VisibilityState.Hidden:
                    startTop = startLineView.Top - _textView.ViewportTop;
                    break;

                case VisibilityState.PartiallyVisible:
                    startTop = startLineView.Top - _textView.ViewportTop;
                    break;

                case VisibilityState.Unattached:
                    // if the closest line was past the end we would have already returned
                    startTop = 0;
                    break;

                default:
                    // shouldn't be reachable, but definitely hide if this is the case
                    IsVisible = false;
                    return;
                }

                if (startTop >= _textView.ViewportHeight + _textView.LineHeight)
                {
                    // shouldn't be reachable, but definitely hide if this is the case
                    IsVisible = false;
                    return;
                }

                double stopBottom;
                switch (endLineView.VisibilityState)
                {
                case VisibilityState.FullyVisible:
                    stopBottom = endLineView.Bottom - _textView.ViewportTop;
                    break;

                case VisibilityState.Hidden:
                    stopBottom = endLineView.Bottom - _textView.ViewportTop;
                    break;

                case VisibilityState.PartiallyVisible:
                    stopBottom = endLineView.Bottom - _textView.ViewportTop;
                    break;

                case VisibilityState.Unattached:
                    // if the closest line was before the start we would have already returned
                    stopBottom = _textView.ViewportHeight;
                    break;

                default:
                    // shouldn't be reachable, but definitely hide if this is the case
                    IsVisible = false;
                    return;
                }

                if (stopBottom <= -_textView.LineHeight)
                {
                    // shouldn't be reachable, but definitely hide if this is the case
                    IsVisible = false;
                    return;
                }

                if (stopBottom <= startTop)
                {
                    if (hunkRangeInfo.IsDeletion)
                    {
                        double center = (startTop + stopBottom) / 2.0;
                        Top       = center - (_textView.LineHeight / 2.0);
                        Height    = _textView.LineHeight;
                        IsVisible = true;
                    }
                    else
                    {
                        // could be reachable if translation changes an addition to empty
                        IsVisible = false;
                    }

                    return;
                }

                Top       = startTop;
                Height    = stopBottom - startTop;
                IsVisible = true;
            }
        }
 public static Difference EmitRemove(int leftStart, int leftEnd, int rightStart, int rightEnd, HunkRangeInfo hunk)
 {
     return(new Difference()
     {
         LeftStartingLineNumber = hunk.OriginalHunkRange.StartingLineNumber,
         RightStartingLineNumber = hunk.NewHunkRange.StartingLineNumber,
         DifferenceType = DifferenceType.Remove,
         Left = new Span()
         {
             Start = hunk.OriginalHunkRange.StartingLineNumber + leftStart,
             Length = leftEnd - leftStart,
             End = hunk.OriginalHunkRange.StartingLineNumber + leftEnd
         },
         Right = new Span()
         {
             Start = rightStart + hunk.NewHunkRange.StartingLineNumber,
             Length = 0, // Zero-length
             End = rightEnd + hunk.NewHunkRange.StartingLineNumber
         }
     });
 }
        private bool?UpdateDeletedDiffDimensions(DiffViewModel diffViewModel, HunkRangeInfo hunkRangeInfo)
        {
            if (hunkRangeInfo.NewHunkRange.NumberOfLines != 0)
            {
                // unexpected number of lines for a deletion hunk
                return(false);
            }

            var snapshot = TextView.TextBuffer.CurrentSnapshot;

            var followingLineNumber = hunkRangeInfo.NewHunkRange.StartingLineNumber + 1;

            if (followingLineNumber < 0 || followingLineNumber >= snapshot.LineCount)
            {
                return(false);
            }

            var followingLine = snapshot.GetLineFromLineNumber(followingLineNumber);

            if (followingLine == null)
            {
                return(null);
            }

            var span = new SnapshotSpan(followingLine.Start, followingLine.End);

            if (!TextView.TextViewLines.FormattedSpan.IntersectsWith(span))
            {
                return(false);
            }

            var followingLineView = TextView.GetTextViewLineContainingBufferPosition(followingLine.Start);

            if (followingLineView == null)
            {
                return(false);
            }

            if (TextView.TextViewLines.LastVisibleLine.EndIncludingLineBreak < followingLineView.Start)
            {
                // starts after the last visible line
                return(false);
            }

            if (TextView.TextViewLines.FirstVisibleLine.Start > followingLineView.EndIncludingLineBreak)
            {
                // ends before the first visible line
                return(false);
            }

            double followingTop;

            switch (followingLineView.VisibilityState)
            {
            case VisibilityState.FullyVisible:
            case VisibilityState.Hidden:
            case VisibilityState.PartiallyVisible:
                followingTop = followingLineView.Top - TextView.ViewportTop;
                break;

            case VisibilityState.Unattached:
                // if the closest line was past the end we would have already returned
                followingTop = 0;
                break;

            default:
                // shouldn't be reachable, but definitely hide if this is the case
                return(false);
            }

            double center = followingTop;
            double height = TextView.LineHeight;

            diffViewModel.Top    = center - (height / 2.0);
            diffViewModel.Height = TextView.LineHeight;
            return(true);
        }
        private bool?UpdateNormalDiffDimensions(DiffViewModel diffViewModel, HunkRangeInfo hunkRangeInfo)
        {
            if (hunkRangeInfo.NewHunkRange.NumberOfLines <= 0)
            {
                // if visible, it would have been as a deletion
                return(false);
            }

            var snapshot = TextView.TextBuffer.CurrentSnapshot;

            var startLineNumber = hunkRangeInfo.NewHunkRange.StartingLineNumber;
            var endLineNumber   = startLineNumber + hunkRangeInfo.NewHunkRange.NumberOfLines - 1;

            if (startLineNumber < 0 ||
                startLineNumber >= snapshot.LineCount ||
                endLineNumber < 0 ||
                endLineNumber >= snapshot.LineCount)
            {
                return(false);
            }

            var startLine = snapshot.GetLineFromLineNumber(startLineNumber);
            var endLine   = snapshot.GetLineFromLineNumber(endLineNumber);

            if (startLine == null || endLine == null)
            {
                return(null);
            }

            var span = new SnapshotSpan(startLine.Start, endLine.End);

            if (!TextView.TextViewLines.FormattedSpan.IntersectsWith(span))
            {
                return(false);
            }

            var startLineView = TextView.GetTextViewLineContainingBufferPosition(startLine.Start);
            var endLineView   = TextView.GetTextViewLineContainingBufferPosition(endLine.Start);

            if (startLineView == null || endLineView == null)
            {
                return(false);
            }

            if (TextView.TextViewLines.LastVisibleLine.EndIncludingLineBreak < startLineView.Start)
            {
                // starts after the last visible line
                return(false);
            }

            if (TextView.TextViewLines.FirstVisibleLine.Start > endLineView.EndIncludingLineBreak)
            {
                // ends before the first visible line
                return(false);
            }

            double startTop;

            switch (startLineView.VisibilityState)
            {
            case VisibilityState.FullyVisible:
            case VisibilityState.Hidden:
            case VisibilityState.PartiallyVisible:
                startTop = startLineView.Top - TextView.ViewportTop;
                break;

            case VisibilityState.Unattached:
                // if the closest line was past the end we would have already returned
                startTop = 0;
                break;

            default:
                // shouldn't be reachable, but definitely hide if this is the case
                return(false);
            }

            double stopBottom;

            switch (endLineView.VisibilityState)
            {
            case VisibilityState.FullyVisible:
            case VisibilityState.Hidden:
            case VisibilityState.PartiallyVisible:
                stopBottom = endLineView.Bottom - TextView.ViewportTop;
                break;

            case VisibilityState.Unattached:
                // if the closest line was before the start we would have already returned
                stopBottom = TextView.ViewportHeight;
                break;

            default:
                // shouldn't be reachable, but definitely hide if this is the case
                return(false);
            }

            diffViewModel.Top    = startTop;
            diffViewModel.Height = stopBottom - startTop;
            return(true);
        }
 protected abstract DiffViewModel CreateDiffViewModel(HunkRangeInfo hunkRangeInfo);
 protected override DiffViewModel CreateDiffViewModel(HunkRangeInfo hunkRangeInfo)
 {
     return(new EditorDiffViewModel(hunkRangeInfo, MarginCore, _updateDiffDimensions));
 }
 internal ScrollDiffViewModel(HunkRangeInfo hunkRangeInfo, IMarginCore marginCore, Action <DiffViewModel, HunkRangeInfo> updateDiffDimensions)
     : base(hunkRangeInfo, marginCore, updateDiffDimensions)
 {
     UpdateDimensions();
 }