예제 #1
0
		LineChangeInfo TransformLineChangeInfo(LineChangeInfo info)
		{
			if (info.Change == ChangeType.Unsaved)
				info.Change = ChangeType.Added;
			
			return info;
		}
        void ILineTracker.LineInserted(DocumentLine insertionPos, DocumentLine newLine)
        {
            int index       = insertionPos.LineNumber;
            var newLineInfo = new LineChangeInfo(ChangeType.Unsaved, index, index);

            changeList[index] = newLineInfo;
            changeList.Insert(index + 1, newLineInfo);
        }
        LineChangeInfo TransformLineChangeInfo(LineChangeInfo info)
        {
            if (info.Change == ChangeType.Unsaved)
            {
                info.Change = ChangeType.Added;
            }

            return(info);
        }
예제 #4
0
        void SetupInitialFileState(bool update)
        {
            if (baseDocument == null)
            {
                if (update)
                {
                    changeList.Transform(TransformLineChangeInfo);
                }
                else
                {
                    changeList.InsertRange(0, document.TotalNumberOfLines + 1, LineChangeInfo.Empty);
                }
            }
            else
            {
                changeList.Clear();

                Dictionary <string, int> hashes = new Dictionary <string, int>();

                MyersDiff.MyersDiff diff = new MyersDiff.MyersDiff(
                    new DocumentSequence(baseDocument, hashes),
                    new DocumentSequence(document, hashes)
                    );

                changeList.Add(LineChangeInfo.Empty);
                int lastEndLine = 0;

                foreach (Edit edit in diff.GetEdits())
                {
                    int beginLine = edit.BeginB;
                    int endLine   = edit.EndB;

                    changeList.InsertRange(changeList.Count, beginLine - lastEndLine, LineChangeInfo.Empty);

                    LineChangeInfo change = new LineChangeInfo(edit.EditType, edit.BeginA, edit.BeginB, edit.EndA, edit.EndB);
                    if (endLine == beginLine)
                    {
                        changeList[changeList.Count - 1] = change;
                    }
                    else
                    {
                        changeList.InsertRange(changeList.Count, endLine - beginLine, change);
                    }

                    lastEndLine = endLine;
                }

                changeList.InsertRange(changeList.Count, textDocument.LineCount - lastEndLine, LineChangeInfo.Empty);
            }

            OnChangeOccurred(EventArgs.Empty);
        }
예제 #5
0
        public bool GetNewVersionFromLine(int lineNumber, out int offset, out int length)
        {
            LineChangeInfo info = changeList[lineNumber];

            if (info.Change != ChangeType.None && info.Change != ChangeType.Unsaved)
            {
                var startLine = document.GetLine(info.NewStartLineNumber + 1);
                var endLine   = document.GetLine(info.NewEndLineNumber);

                offset = startLine.Offset;
                length = endLine.EndOffset - startLine.Offset;
                return(true);
            }

            offset = length = 0;
            return(false);
        }
        protected override void OnRender(DrawingContext drawingContext)
        {
            Size     renderSize = this.RenderSize;
            TextView textView   = this.TextView;

            if (textView != null && textView.VisualLinesValid)
            {
                var zeroLineInfo = changeWatcher.GetChange(0);

                foreach (VisualLine line in textView.VisualLines)
                {
                    Rect rect = new Rect(0, line.VisualTop - textView.ScrollOffset.Y - 1, 5, line.Height + 2);

                    LineChangeInfo info = changeWatcher.GetChange(line.FirstDocumentLine.LineNumber);

                    if (zeroLineInfo.Change == ChangeType.Deleted && line.FirstDocumentLine.LineNumber == 1 && info.Change != ChangeType.Unsaved)
                    {
                        info.Change = ChangeType.Modified;
                    }

                    switch (info.Change)
                    {
                    case ChangeType.None:
                        break;

                    case ChangeType.Added:
                        drawingContext.DrawRectangle(AddedLineBrush, null, rect);
                        break;

                    case ChangeType.Deleted:
                    case ChangeType.Modified:
                        drawingContext.DrawRectangle(ChangedLineBrush, null, rect);
                        break;

                    case ChangeType.Unsaved:
                        drawingContext.DrawRectangle(UnsavedLineBrush, null, rect);
                        break;

                    default:
                        throw new Exception("Invalid value for ChangeType");
                    }
                }
            }
        }
예제 #7
0
		public bool GetNewVersionFromLine(int lineNumber, out int offset, out int length)
		{
			LineChangeInfo info = changeList[lineNumber];
			
			if (info.Change != ChangeType.None && info.Change != ChangeType.Unsaved) {
				var startLine = document.GetLineByNumber(CalculateNewStartLineNumber(lineNumber));
				var endLine = document.GetLineByNumber(CalculateNewEndLineNumber(lineNumber));
				
				offset = startLine.Offset;
				length = endLine.EndOffset - startLine.Offset;
				
				if (info.Change == ChangeType.Added)
					length += endLine.DelimiterLength;
				
				return true;
			}
			
			offset = length = 0;
			return false;
		}
예제 #8
0
		public string GetOldVersionFromLine(int lineNumber, out int newStartLine, out bool added)
		{
			LineChangeInfo info = changeList[lineNumber];
			
			added = info.Change == ChangeType.Added;
			
			if (info.Change != ChangeType.None && info.Change != ChangeType.Unsaved) {
				newStartLine = CalculateNewStartLineNumber(lineNumber);
				
				if (info.Change == ChangeType.Added)
					return "";
				
				var startDocumentLine = baseDocument.GetLineByNumber(info.OldStartLineNumber + 1);
				var endLine = baseDocument.GetLineByNumber(info.OldEndLineNumber);
				
				return TextUtilities.NormalizeNewLines(baseDocument.GetText(startDocumentLine.Offset, endLine.EndOffset - startDocumentLine.Offset), DocumentUtilities.GetLineTerminator(document, newStartLine == 0 ? 1 : newStartLine));
			}
			
			newStartLine = 0;
			return null;
		}
예제 #9
0
        protected override void OnRender(DrawingContext drawingContext)
        {
            Size     renderSize = this.RenderSize;
            TextView textView   = this.TextView;

            if (textView != null && textView.VisualLinesValid)
            {
                foreach (VisualLine line in textView.VisualLines)
                {
                    Rect rect = new Rect(0, line.VisualTop - textView.ScrollOffset.Y, 5, line.Height);

                    LineChangeInfo info = changeWatcher.GetChange(line.FirstDocumentLine.LineNumber);

                    switch (info.Change)
                    {
                    case ChangeType.None:
                        break;

                    case ChangeType.Added:
                        drawingContext.DrawRectangle(Brushes.LightGreen, null, rect);
                        break;

                    case ChangeType.Deleted:
                    case ChangeType.Modified:
                        drawingContext.DrawRectangle(Brushes.LightBlue, null, rect);
                        break;

                    case ChangeType.Unsaved:
                        drawingContext.DrawRectangle(Brushes.Yellow, null, rect);
                        break;

                    default:
                        throw new Exception("Invalid value for ChangeType");
                    }
                }
            }
        }
예제 #10
0
        public string GetOldVersionFromLine(int lineNumber, out int newStartLine, out bool added)
        {
            LineChangeInfo info = changeList[lineNumber];

            added = info.Change == ChangeType.Added;

            if (info.Change != ChangeType.None && info.Change != ChangeType.Unsaved)
            {
                newStartLine = info.NewStartLineNumber + 1;

                if (info.Change == ChangeType.Added)
                {
                    return("");
                }

                var startDocumentLine = baseDocument.GetLine(info.OldStartLineNumber + 1);
                var endLine           = baseDocument.GetLine(info.OldEndLineNumber);

                return(baseDocument.GetText(startDocumentLine.Offset, endLine.EndOffset - startDocumentLine.Offset));
            }

            newStartLine = 0;
            return(null);
        }
        void DisplayTooltip(MouseEventArgs e)
        {
            int line = GetLineFromMousePosition(e);

            if (line == 0)
            {
                return;
            }

            int    startLine;
            bool   added;
            string oldText = changeWatcher.GetOldVersionFromLine(line, out startLine, out added);

            TextEditor editor = this.TextView.GetService <TextEditor>();

            markerService = this.TextView.GetService <ITextMarkerService>();

            LineChangeInfo zeroLineInfo = changeWatcher.GetChange(0);

            int  offset, length;
            bool hasNewVersion = changeWatcher.GetNewVersionFromLine(line, out offset, out length);

            if (line == 1 && zeroLineInfo.Change == ChangeType.Deleted)
            {
                int zeroStartLine; bool zeroAdded;
                startLine = 1;
                string deletedText = changeWatcher.GetOldVersionFromLine(0, out zeroStartLine, out zeroAdded);
                var    docLine     = editor.Document.GetLineByNumber(line);
                string newLine     = DocumentUtilities.GetLineTerminator(changeWatcher.CurrentDocument, 1);
                deletedText += newLine;
                deletedText += editor.Document.GetText(docLine.Offset, docLine.Length);
                if (oldText != null)
                {
                    oldText = deletedText + newLine + oldText;
                }
                else
                {
                    oldText = deletedText;
                }

                if (!hasNewVersion)
                {
                    offset        = 0;
                    length        = docLine.Length;
                    hasNewVersion = true;
                }
            }

            if (hasNewVersion)
            {
                if (marker != null)
                {
                    markerService.Remove(marker);
                }
                if (length <= 0)
                {
                    marker = null;
                    length = 0;
                }
                else
                {
                    marker = markerService.Create(offset, length);
                    marker.BackgroundColor = Colors.LightGreen;
                }
            }

            if (oldText != null)
            {
                LineChangeInfo currLineInfo = changeWatcher.GetChange(startLine);

                if (currLineInfo.Change == ChangeType.Deleted && !(line == 1 && zeroLineInfo.Change == ChangeType.Deleted))
                {
                    var docLine = editor.Document.GetLineByNumber(startLine);
                    if (docLine.DelimiterLength == 0)
                    {
                        oldText = DocumentUtilities.GetLineTerminator(changeWatcher.CurrentDocument, startLine) + oldText;
                    }
                    oldText = editor.Document.GetText(docLine.Offset, docLine.TotalLength) + oldText;
                }

                DiffControl differ = new DiffControl();
                differ.CopyEditorSettingsAndHighlighting(editor);
                differ.editor.Document.Text = oldText;

                if (oldText == string.Empty)
                {
                    differ.editor.Visibility     = Visibility.Collapsed;
                    differ.copyButton.Visibility = Visibility.Collapsed;
                }
                else
                {
                    if (differ.editor.SyntaxHighlighting != null)
                    {
                        var baseDocument     = new ReadOnlyDocument(changeWatcher.BaseDocument, TextView.Document.FileName);
                        var mainHighlighter  = new DocumentHighlighter(baseDocument, differ.editor.SyntaxHighlighting);
                        var popupHighlighter = differ.editor.TextArea.GetService(typeof(IHighlighter)) as DocumentHighlighter;

                        popupHighlighter.InitialSpanStack = mainHighlighter.GetSpanStack(currLineInfo.OldStartLineNumber);
                    }
                }

                differ.revertButton.Click += delegate {
                    if (hasNewVersion)
                    {
                        Document.Replace(offset, length, oldText);
                        tooltip.IsOpen = false;
                    }
                };

                const double borderThickness = 1;
                tooltip.Child = new Border {
                    Child           = differ,
                    BorderBrush     = editor.TextArea.Foreground,
                    BorderThickness = new Thickness(borderThickness)
                };

                if (tooltip.IsOpen)
                {
                    tooltip.IsOpen = false;
                }

                tooltip.Closed += delegate {
                    if (marker != null)
                    {
                        markerService.Remove(marker);
                    }
                };
                tooltip.HorizontalOffset = -borderThickness - TextView.ScrollOffset.X;
                tooltip.VerticalOffset   =
                    TextView.GetVisualTopByDocumentLine(startLine) - TextView.ScrollOffset.Y;
                tooltip.Placement       = PlacementMode.Top;
                tooltip.PlacementTarget = this.TextView;

                tooltip.IsOpen = true;
            }
        }
예제 #12
0
        void DisplayTooltip(MouseEventArgs e)
        {
            int line = GetLineFromMousePosition(e);

            if (line == 0)
            {
                return;
            }

            int    startLine;
            bool   added;
            string oldText = changeWatcher.GetOldVersionFromLine(line, out startLine, out added);

            TextEditor editor = this.TextView.Services.GetService(typeof(TextEditor)) as TextEditor;

            markerService = this.TextView.Services.GetService(typeof(ITextMarkerService)) as ITextMarkerService;

            int  offset, length;
            bool hasNewVersion = changeWatcher.GetNewVersionFromLine(line, out offset, out length);

            if (hasNewVersion)
            {
                if (marker != null)
                {
                    markerService.Remove(marker);
                }
                if (length <= 0)
                {
                    marker = null;
                    length = 0;
                }
                else
                {
                    marker = markerService.Create(offset, length);
                    marker.BackgroundColor = Colors.LightGreen;
                }
            }

            if (oldText != null)
            {
                DiffControl differ = new DiffControl();
                differ.editor.SyntaxHighlighting            = editor.SyntaxHighlighting;
                differ.editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
                differ.editor.VerticalScrollBarVisibility   = ScrollBarVisibility.Hidden;
                differ.editor.Document.Text = oldText;
                differ.Background           = Brushes.White;

                // TODO : deletions on line 0 cannot be displayed.

                LineChangeInfo prevLineInfo = changeWatcher.GetChange(startLine - 1);
                LineChangeInfo lineInfo     = changeWatcher.GetChange(startLine);

                if (prevLineInfo.Change == ChangeType.Deleted)
                {
                    var docLine = editor.Document.GetLineByNumber(startLine - 1);
                    differ.editor.Document.Insert(0, editor.Document.GetText(docLine.Offset, docLine.TotalLength));
                }

                if (oldText == string.Empty)
                {
                    differ.editor.Visibility     = Visibility.Collapsed;
                    differ.copyButton.Visibility = Visibility.Collapsed;
                }
                else
                {
                    var baseDocument = new TextDocument(changeWatcher.BaseDocument.Text);
                    if (differ.editor.SyntaxHighlighting != null)
                    {
                        var mainHighlighter  = new DocumentHighlighter(baseDocument, differ.editor.SyntaxHighlighting.MainRuleSet);
                        var popupHighlighter = differ.editor.TextArea.GetService(typeof(IHighlighter)) as DocumentHighlighter;

                        if (prevLineInfo.Change == ChangeType.Deleted)
                        {
                            popupHighlighter.InitialSpanStack = mainHighlighter.GetSpanStack(prevLineInfo.OldStartLineNumber);
                        }
                        else
                        {
                            popupHighlighter.InitialSpanStack = mainHighlighter.GetSpanStack(lineInfo.OldStartLineNumber);
                        }
                    }
                }

                differ.revertButton.Click += delegate {
                    if (hasNewVersion)
                    {
                        int          delimiter = 0;
                        DocumentLine l         = Document.GetLineByOffset(offset + length);
                        if (added)
                        {
                            delimiter = l.DelimiterLength;
                        }
                        if (length == 0)
                        {
                            oldText += DocumentUtilitites.GetLineTerminator(new AvalonEditDocumentAdapter(Document, null), l.LineNumber);
                        }
                        Document.Replace(offset, length + delimiter, oldText);
                        tooltip.IsOpen = false;
                    }
                };

                tooltip.Child = new Border()
                {
                    Child           = differ,
                    BorderBrush     = Brushes.Black,
                    BorderThickness = new Thickness(1)
                };

                if (tooltip.IsOpen)
                {
                    tooltip.IsOpen = false;
                }

                tooltip.IsOpen = true;

                tooltip.Closed += delegate {
                    if (marker != null)
                    {
                        markerService.Remove(marker);
                    }
                };
                tooltip.HorizontalOffset = -10;
                tooltip.VerticalOffset   =
                    TextView.GetVisualTopByDocumentLine(startLine) - TextView.ScrollOffset.Y;
                tooltip.Placement       = PlacementMode.Top;
                tooltip.PlacementTarget = this.TextView;
            }
        }