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 } }); }
protected DiffViewModel(HunkRangeInfo hunkRangeInfo, IMarginCore marginCore, Action <DiffViewModel, HunkRangeInfo> updateDiffDimensions) { HunkRangeInfo = hunkRangeInfo; MarginCore = marginCore; _updateDiffDimensions = updateDiffDimensions; MarginCore.BrushesChanged += HandleBrushesChanged; }
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); } }
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"); }
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(); }
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); }
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(); }