public bool GoToLine() { int maxLineNumber = 0; if (this.lines != null) { for (int i = this.lines.Count - 1; i >= 0; i--) { DiffViewLine line = this.lines[i]; if (line.Number.HasValue) { // Add 1 because display numbers are 1-based. maxLineNumber = line.Number.Value + 1; break; } } } bool result = false; if (maxLineNumber > 0) { using (GoToDialog dialog = new()) { if (dialog.Execute(this, maxLineNumber, out int line)) { // Subtract 1 because the dialog returns a 1-based number result = this.GoToLine(line - 1); } } } return(result); }
public DisplayLine(DiffViewLine line, bool showWhitespace, int spacesPerTab) : this() { this.line = line; this.showWhitespace = showWhitespace; this.spacesPerTab = spacesPerTab; }
public bool GoToLine(int line) { bool result = false; // We know the original line number will be in a DiffViewLine at a position >= iLine. if (line >= 0 && this.lines != null && line < this.lines.Count) { for (int i = line; i < this.lines.Count; i++) { DiffViewLine diffLine = this.lines[i]; if (diffLine.Number.HasValue && diffLine.Number.Value == line) { this.GoToPosition(i, 0); result = true; } } } return(result); }
public void SetCounterpartLines(DiffView counterpartView) { int numLines = this.LineCount; if (numLines != counterpartView.LineCount) { throw new ArgumentException("The counterpart view has a different number of view lines.", nameof(counterpartView)); } if (this.lines != null && counterpartView.lines != null) { for (int i = 0; i < numLines; i++) { DiffViewLine line = this.lines[i]; DiffViewLine counterpart = counterpartView.lines[i]; // Make the counterpart lines refer to each other. line.Counterpart = counterpart; counterpart.Counterpart = line; } } }
private void RenderImage() { if (this.image != null) { this.image.Dispose(); this.image = null; } int width = this.ClientSize.Width; int height = this.ClientSize.Height; if (width > 0 && height > 0 && this.view != null && this.view.Lines != null) { // Draw a bitmap in memory that we can render from this.image = new Bitmap(width, height); using (Graphics g = Graphics.FromImage(this.image)) using (SolidBrush backBrush = new(this.BackColor)) { g.FillRectangle(backBrush, 0, 0, width, height); const float GutterWidth = 2.0F; // Make sure each line is at least 1 pixel high float lineHeight = (float)Math.Max(1.0, this.GetPixelLineHeightF(1)); DiffViewLines lines = this.view.Lines; int numLines = lines.Count; for (int i = 0; i < numLines; i++) { DiffViewLine line = lines[i]; if (line.Edited) { backBrush.Color = DiffOptions.GetColorForEditType(line.EditType); float y = this.GetPixelLineHeightF(i); float fullFillWidth = width - (2 * GutterWidth); switch (line.EditType) { case EditType.Change: // Draw all the way across g.FillRectangle(backBrush, GutterWidth, y, fullFillWidth, lineHeight); break; case EditType.Delete: // Draw delete on the left and dead space on the right. g.FillRectangle(backBrush, GutterWidth, y, fullFillWidth / 2, lineHeight); using (Brush? deadBrush = DiffOptions.TryCreateDeadSpaceBrush(backBrush.Color)) { g.FillRectangle(deadBrush ?? backBrush, GutterWidth + (fullFillWidth / 2), y, fullFillWidth / 2, lineHeight); } break; case EditType.Insert: // Draw dead space on the left and insert on the right. using (Brush? deadBrush = DiffOptions.TryCreateDeadSpaceBrush(backBrush.Color)) { g.FillRectangle(deadBrush ?? backBrush, GutterWidth, y, fullFillWidth / 2, lineHeight); } g.FillRectangle(backBrush, GutterWidth + (fullFillWidth / 2), y, fullFillWidth / 2, lineHeight); break; } } } } } }
public void SetData(DiffViewLine lineOne, DiffViewLine lineTwo) { this.lines = new DiffViewLines(lineOne, lineTwo); this.UpdateAfterSetData(); }
protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); // Get scroll positions int posY = this.VScrollPos; int posX = this.HScrollPos; // Find painting limits int numLines = this.LineCount; int firstLine = Math.Max(0, posY + (e.ClipRectangle.Top / this.lineHeight)); int lastCalcLine = posY + (e.ClipRectangle.Bottom / this.lineHeight); int lastLine = Math.Min(numLines - 1, lastCalcLine); // Create some graphics objects Graphics g = e.Graphics; using (SolidBrush fontBrush = new(this.Enabled ? this.ForeColor : SystemColors.GrayText)) using (SolidBrush backBrush = new(this.BackColor)) { // We can't free GutterBrush since it is a system brush. Brush gutterBrush = SystemBrushes.Control; // Set the correct origin for HatchBrushes (used when painting dead space). g.RenderingOrigin = new Point(-posX, -posY); // See what we need to paint. For horz scrolling, // the gutter won't need it. For focus changes, // the lines won't need it. bool paintGutter = e.ClipRectangle.X < this.gutterWidth; bool paintLine = e.ClipRectangle.X + e.ClipRectangle.Width >= this.gutterWidth; bool hasFocus = this.Focused; // Indent the gutter text horizontally a little bit int lineNumIndent = this.charWidth / 2; // This centers it since it has 1 extra char width // Determine the selection positions in forward order bool hasSelection = this.HasSelection; this.GetForwardOrderSelection(out DiffViewPosition startSel, out DiffViewPosition endSel); // Paint each line if (this.lines != null) { for (int i = firstLine; i <= lastLine; i++) { // If we get inside this loop there must be at least one line. Debug.Assert(this.LineCount > 0, "There must be at least one line."); int x = (this.charWidth * (-posX)) + this.gutterWidth; int y = this.lineHeight * (i - posY); DiffViewLine line = this.lines[i]; if (paintLine) { this.DrawLine(g, fontBrush, backBrush, hasFocus, i, line, x, y, hasSelection, startSel, endSel); } if (paintGutter) { this.DrawGutter(g, fontBrush, backBrush, hasFocus, i, line, y, gutterBrush, lineNumIndent); } } } // Draw the background and an empty gutter for any // blank lines past the end of the actual lines. backBrush.Color = this.BackColor; for (int i = lastLine + 1; i <= lastCalcLine; i++) { int y = this.lineHeight * (i - posY); this.DrawBackground(g, backBrush, y, true); if (paintGutter) { this.DrawGutterBackground(g, gutterBrush, backBrush, y); } } } }