private BlameLayout(BlameLayout layout, int?topLineNumber = null, Size?renderSize = null, double?lineHeight = null, double?lineNumberColumnWidth = null, double?codeColumnWidth = null, bool fullRefresh = false) : this(layout.m_blame, fullRefresh ? GetBlameAuthors(layout.m_blame) : layout.m_authorIndex, layout.m_columnWidths) { // copy or replace values from other BlameLayout TopLineNumber = topLineNumber ?? layout.TopLineNumber; m_renderSize = renderSize ?? layout.m_renderSize; LineHeight = lineHeight ?? layout.LineHeight; m_columnWidths[c_lineNumberColumnIndex] = lineNumberColumnWidth ?? m_columnWidths[c_lineNumberColumnIndex]; m_columnWidths[c_codeColumnIndex] = codeColumnWidth ?? m_columnWidths[c_codeColumnIndex]; m_oldestCommit = fullRefresh ? GetOldestCommit(m_blame) : layout.m_oldestCommit; m_dateScale = fullRefresh ? GetDateScale(m_blame, m_oldestCommit) : layout.m_dateScale; // calculate new values LineCount = (int)Math.Ceiling(m_renderSize.Height / LineHeight); }
private void Render(DrawingContext drawingContext) { drawingContext.DrawRectangle(Brushes.White, null, new Rect(new Point(), RenderSize)); if (m_blame == null || m_emSize == 0) return; Typeface typeface = TextElementUtility.GetTypeface(this); BlameLayout layout = m_layout.WithRenderSize(RenderSize); foreach (Rect newLineRectangle in layout.NewLines) drawingContext.DrawRectangle(m_newLineBrush, null, newLineRectangle); foreach (DisplayBlock block in layout.Blocks) { Rect blockRectangle = block.CommitPosition; drawingContext.DrawRectangle(m_personBrush[block.AuthorIndex], null, block.AuthorPosition); drawingContext.DrawRectangle(GetOrCreateCommitBrush(block), null, blockRectangle); drawingContext.DrawLine(new Pen(Brushes.LightGray, 1), new Point(0, blockRectangle.Bottom + 0.5), new Point(RenderSize.Width, blockRectangle.Bottom + 0.5)); FormattedText authorText = CreateSmallFormattedText(block.AuthorName, typeface, block.AuthorWidth); drawingContext.DrawText(authorText, new Point(block.AuthorX, block.TextY)); FormattedText dateText = CreateSmallFormattedText(block.Date, typeface, block.DateWidth); dateText.TextAlignment = TextAlignment.Right; drawingContext.DrawText(dateText, new Point(block.DateX, block.TextY)); if (block.ShowsSummary) { Rect summaryPosition = block.SummaryPosition; FormattedText commitText = CreateSmallFormattedText(block.Summary, typeface, summaryPosition.Width); commitText.MaxLineCount = Math.Max(1, (int) (summaryPosition.Height / commitText.Height)); commitText.Trimming = TextTrimming.WordEllipsis; drawingContext.DrawText(commitText, summaryPosition.TopLeft); } } Column lineNumberColumn = layout.LineNumberColumn; double yOffset = 0; double lineNumberWidth = lineNumberColumn.Width; foreach (DisplayLine line in layout.Lines) { FormattedText lineNumberText = CreateFormattedText(line.LineNumber.ToString(CultureInfo.InvariantCulture), typeface); lineNumberText.TextAlignment = TextAlignment.Right; lineNumberText.SetForegroundBrush(Brushes.DarkCyan); lineNumberWidth = Math.Max(lineNumberWidth, lineNumberText.Width); lineNumberText.MaxTextWidth = lineNumberWidth; drawingContext.DrawText(lineNumberText, new Point(lineNumberColumn.Left, yOffset)); yOffset += layout.LineHeight; } layout = layout.WithLineNumberWidth(lineNumberWidth); Column codeColumn = layout.CodeColumn; Geometry clipGeometry = new RectangleGeometry(new Rect(codeColumn.Left, 0, RenderSize.Width - codeColumn.Left, RenderSize.Height)); drawingContext.PushClip(clipGeometry); yOffset = 0; foreach (DisplayLine line in layout.Lines) { double xOffset = layout.CodeColumn.Left - HorizontalOffset; foreach (LinePart part in line.Parts) { FormattedText text = CreateFormattedText(string.Join("", part.Text.Replace("\t", " ")), typeface); if (!line.IsNew && part.Status == LinePartStatus.New) drawingContext.DrawRectangle(m_changedTextBrush, null, new Rect(xOffset, yOffset, text.WidthIncludingTrailingWhitespace, layout.LineHeight)); drawingContext.DrawText(text, new Point(xOffset, yOffset)); xOffset += text.WidthIncludingTrailingWhitespace; } layout = layout.WithCodeWidth(xOffset - codeColumn.Left + HorizontalOffset); yOffset += layout.LineHeight; } drawingContext.Pop(); double commitRightX = layout.CommitColumn.Right; drawingContext.DrawLine(new Pen(Brushes.DarkGray, 1), new Point(commitRightX, 0), new Point(commitRightX, Math.Min(yOffset, RenderSize.Height))); double lineNumberRightX = layout.CodeMarginColumn.Right; drawingContext.DrawLine(new Pen(Brushes.DarkGray, 1), new Point(lineNumberRightX, 0), new Point(lineNumberRightX, Math.Min(yOffset, RenderSize.Height))); SetHorizontalScrollInfo(layout.Width, RenderSize.Width, null); if (layout != m_layout) { m_layout = layout; RedrawSoon(); } }
private void OnBlameResultPropertyChanged(PropertyChangedEventArgs e) { bool fullRefresh = e.PropertyName == null; m_layout = m_layout.Refresh(fullRefresh); if (fullRefresh) { m_personBrush.Clear(); CreateBrushesForAuthors(m_layout.AuthorCount); } RedrawSoon(); }
protected override void OnScrollChanged() { m_layout = m_layout.WithTopLineNumber((int) VerticalOffset + 1); if (RenderSize.Width > 0 && RenderSize.Height > 0) Render(); }
protected override Size MeasureOverride(Size availableSize) { if (m_layout != null) { Typeface typeface = TextElementUtility.GetTypeface(this); m_emSize = Math.Max(TextElement.GetFontSize(this), 10.0 * 4 / 3); FormattedText text = CreateFormattedText("8888", typeface); m_layout = m_layout.WithLineHeight(text.Height); } return availableSize; }
protected override Size ArrangeOverride(Size finalSize) { if (m_layout != null) { m_layout = m_layout.WithRenderSize(finalSize); SetVerticalScrollInfo(null, finalSize.Height / m_layout.LineHeight, null); RedrawSoon(); } return finalSize; }
internal void SetBlameResult(BlameResult blame, int topLineNumber = 1) { if (m_blameSubscription != null) m_blameSubscription.Dispose(); double oldLineHeight = m_layout == null ? 1.0 : m_layout.LineHeight; m_blame = blame; m_layout = new BlameLayout(blame).WithTopLineNumber(1).WithLineHeight(oldLineHeight); m_lineCount = blame.Blocks.Sum(b => b.LineCount); m_blameSubscription = Observable.FromEventPattern<PropertyChangedEventArgs>(m_blame, "PropertyChanged").ObserveOnDispatcher().Subscribe(x => OnBlameResultPropertyChanged(x.EventArgs)); m_hoverCommitId = null; m_selectedCommitId = null; m_personBrush.Clear(); m_commitBrush.Clear(); m_commitAlpha.Clear(); CreateBrushesForAuthors(m_layout.AuthorCount); SetVerticalScrollInfo(m_lineCount + 1, null, topLineNumber - 1); InvalidateMeasure(); OnScrollChanged(); RedrawSoon(); }
internal void ClearBlameResult() { m_blame = null; m_layout = null; SetHorizontalScrollInfo(1, null, 0); SetVerticalScrollInfo(1, null, 0); InvalidateMeasure(); RedrawSoon(); }
private BlameLayout(BlameLayout layout, int? topLineNumber = null, Size? renderSize = null, double? lineHeight = null, double? lineNumberColumnWidth = null, double? codeColumnWidth = null, bool fullRefresh = false) : this() { // copy values from other BlameLayout m_blame = layout.m_blame; m_columnWidths = layout.m_columnWidths; // copy or replace values from other BlameLayout m_topLineNumber = topLineNumber ?? layout.m_topLineNumber; m_renderSize = renderSize ?? layout.m_renderSize; m_lineHeight = lineHeight ?? layout.m_lineHeight; m_columnWidths[c_lineNumberColumnIndex] = lineNumberColumnWidth ?? m_columnWidths[c_lineNumberColumnIndex]; m_columnWidths[c_codeColumnIndex] = codeColumnWidth ?? m_columnWidths[c_codeColumnIndex]; m_authorIndex = fullRefresh ? GetBlameAuthors(m_blame) : layout.m_authorIndex; m_oldestCommit = fullRefresh ? GetOldestCommit(m_blame) : layout.m_oldestCommit; m_dateScale = fullRefresh ? GetDateScale(m_blame, m_oldestCommit) : layout.m_dateScale; // calculate new values m_lineCount = (int) Math.Ceiling(m_renderSize.Height / m_lineHeight); }