internal void UpdateText() { if (Text == null) { return; } CanvasRoot.Height = Text.LineCount * LineHeight; CanvasRoot.Invalidate(); GutterRoot.Text = this.Text; GutterRoot.UpdateHeight(CanvasRoot.Height); if (DiffMap != null) { DiffMap.UpdateTextViews(); } Text.ScrollToLineRequested -= Text_ScrollToLineRequested; Text.ScrollToLineRequested += Text_ScrollToLineRequested; }
private void canvas_RegionsInvalidated(CanvasVirtualControl sender, CanvasRegionsInvalidatedEventArgs args) { if (Text == null) { return; } // Update the diff map if (_parentScrollViewer == null) { _parentScrollViewer = VisualTreeHelper.FindParent <ScrollViewer>(this); if (_parentScrollViewer != null) { _parentScrollViewer.ViewChanged += (s, e) => { if (DiffMap != null) { DiffMap.UpdateTextViews(); } }; // Force update once if (DiffMap != null) { DiffMap.UpdateTextViews(); } } } if (_language == null && !string.IsNullOrEmpty(FileExtension)) { _language = Languages.FindById(FileExtension); } foreach (Windows.Foundation.Rect region in args.InvalidatedRegions) { using (CanvasDrawingSession ds = sender.CreateDrawingSession(region)) { ds.Clear(_defaultBackgroundColor); int startLine = (int)Math.Clamp(Math.Floor(region.Top / LineHeight), 0, Text.LineCount); // add 2 to the end line count. we want to "overdraw" a bit if the line is going to be cut-off int endLine = (int)Math.Clamp(Math.Ceiling(region.Bottom / LineHeight) + 2, 0, Text.LineCount); StringBuilder stringRegion = new StringBuilder(); for (int i = startLine; i < endLine; i++) { ITextLine line = Text.GetLine(i); if (line is DiffTextLine diffLine) { if (diffLine.ChangeType == DiffLineType.Empty) { stringRegion.AppendLine(); // null line } else { stringRegion.AppendLine(Text.GetLine(i).ToString()); } } } using (var canvasText = new CanvasTextLayout(ds, stringRegion.ToString(), _textFormat, 9999, (float)region.Height)) { // Handle the diff line background colors int index = 0; for (int i = startLine; i < endLine; i++) { var line = Text.GetLine(i); if (line is DiffTextLine diffLine) { switch (diffLine.ChangeType) { case DiffLineType.Insert: { ds.FillRectangle(0, i * LineHeight, (float)this.ActualWidth, MathF.Ceiling(LineHeight), _addedBackgroundColor); if (_language == null) { canvasText.SetBrush(index, line.Length, _addedForegroundBrush); } } break; case DiffLineType.Remove: { ds.FillRectangle(0, i * LineHeight, (float)this.ActualWidth, MathF.Ceiling(LineHeight), _removedBackgroundColor); if (_language == null) { canvasText.SetBrush(index, line.Length, _removedForegroundBrush); } } break; case DiffLineType.Empty: { ds.FillRectangle(0, i * LineHeight, (float)this.ActualWidth, MathF.Ceiling(LineHeight), _nullBrush); } break; case DiffLineType.Unchanged: default: break; } } index += line.Length + 2; // add for newline } // Syntax highlight if (_language != null) { _colorizer.FormatLine(_language, CanvasRoot, canvasText, stringRegion.ToString()); } // Draw the text ds.DrawTextLayout(canvasText, 0, startLine * LineHeight, _defaultForegroundBrush); } } } }