using ICSharpCode.AvalonEdit.Rendering; using System.Windows.Media; using System; using System.Windows; using ICSharpCode.AvalonEdit.Document; namespace CodeMerger; public class ChangesHighlightingColorizer : IBackgroundRenderer { private static readonly Brush AddedLineBrush = new SolidColorBrush(Color.FromArgb(40, 50, 205, 50)); // Verde más visible private static readonly Brush ModifiedLineBrush = new SolidColorBrush(Color.FromArgb(40, 255, 215, 0)); // Amarillo más visible private TextView _textView; public KnownLayer Layer => KnownLayer.Background; public void SetTextView(TextView textView) { if (_textView != null) _textView.VisualLinesChanged -= TextView_VisualLinesChanged; _textView = textView; _textView.VisualLinesChanged += TextView_VisualLinesChanged; } private void TextView_VisualLinesChanged(object sender, EventArgs e) { _textView?.InvalidateLayer(Layer); } public void Draw(TextView textView, DrawingContext drawingContext) { if (textView?.Document == null) return; bool isInAddedSection = false; bool isInModifiedSection = false; int sectionStartDepth = 0; int currentDepth = 0; int currentLine = 1; int totalLines = textView.Document.LineCount; while (currentLine <= totalLines) { var documentLine = textView.Document.GetLineByNumber(currentLine); var lineText = textView.Document.GetText(documentLine); var trimmedText = lineText.Trim(); // Actualizar el nivel de anidación currentDepth += CountOpenBraces(trimmedText) - CountCloseBraces(trimmedText); // Detectar inicio de secciones if (trimmedText.Contains("// Added:") || trimmedText.Contains("// New:")) { isInAddedSection = true; isInModifiedSection = false; sectionStartDepth = currentDepth; } else if (trimmedText.Contains("// Modified:") || trimmedText.Contains("// Changed:")) { isInAddedSection = false; isInModifiedSection = true; sectionStartDepth = currentDepth; } // Obtener la línea visual var visualLine = textView.GetOrConstructVisualLine(documentLine); if (visualLine != null) { // Determinar el color basado en el estado actual Brush brush = null; if (isInAddedSection) { brush = AddedLineBrush; } else if (isInModifiedSection) { brush = ModifiedLineBrush; } // Si tenemos un color asignado y no es una línea de separador if (brush != null && !trimmedText.Contains("// ----------------------------------------")) { var rect = BackgroundGeometryBuilder.GetRectsFromVisualSegment(textView, visualLine, 0, 1000) .First(); // Dibujar el fondo de la línea completa drawingContext.DrawRectangle( brush, null, new Rect(0, rect.Top, textView.ActualWidth, rect.Height) ); } } // Detectar fin de secciones // Si volvemos al mismo nivel de anidación donde empezó la sección y encontramos una llave de cierre if ((isInAddedSection || isInModifiedSection) && currentDepth <= sectionStartDepth && trimmedText.Contains("}")) { isInAddedSection = false; isInModifiedSection = false; } // También terminar sección si encontramos un nuevo marcador if (trimmedText.Contains("// ----------------------------------------")) { isInAddedSection = false; isInModifiedSection = false; } currentLine++; } } private int CountOpenBraces(string text) { return text.Count(c => c == '{'); } private int CountCloseBraces(string text) { return text.Count(c => c == '}'); } }