Skip to content

Commit 0476a82

Browse files
committed
code_style: move some code from Histories.axaml to separate files
Signed-off-by: leo <[email protected]>
1 parent bb2284c commit 0476a82

File tree

6 files changed

+704
-671
lines changed

6 files changed

+704
-671
lines changed

src/Views/CommitGraph.cs

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
using Avalonia;
2+
using Avalonia.Controls;
3+
using Avalonia.Media;
4+
using Avalonia.VisualTree;
5+
6+
namespace SourceGit.Views
7+
{
8+
public class CommitGraph : Control
9+
{
10+
public static readonly StyledProperty<Models.CommitGraph> GraphProperty =
11+
AvaloniaProperty.Register<CommitGraph, Models.CommitGraph>(nameof(Graph));
12+
13+
public Models.CommitGraph Graph
14+
{
15+
get => GetValue(GraphProperty);
16+
set => SetValue(GraphProperty, value);
17+
}
18+
19+
public static readonly StyledProperty<IBrush> DotBrushProperty =
20+
AvaloniaProperty.Register<CommitGraph, IBrush>(nameof(DotBrush), Brushes.Transparent);
21+
22+
public IBrush DotBrush
23+
{
24+
get => GetValue(DotBrushProperty);
25+
set => SetValue(DotBrushProperty, value);
26+
}
27+
28+
public static readonly StyledProperty<bool> OnlyHighlightCurrentBranchProperty =
29+
AvaloniaProperty.Register<CommitGraph, bool>(nameof(OnlyHighlightCurrentBranch), true);
30+
31+
public bool OnlyHighlightCurrentBranch
32+
{
33+
get => GetValue(OnlyHighlightCurrentBranchProperty);
34+
set => SetValue(OnlyHighlightCurrentBranchProperty, value);
35+
}
36+
37+
static CommitGraph()
38+
{
39+
AffectsRender<CommitGraph>(GraphProperty, DotBrushProperty, OnlyHighlightCurrentBranchProperty);
40+
}
41+
42+
public override void Render(DrawingContext context)
43+
{
44+
base.Render(context);
45+
46+
var graph = Graph;
47+
if (graph == null)
48+
return;
49+
50+
var histories = this.FindAncestorOfType<Histories>();
51+
if (histories == null)
52+
return;
53+
54+
var list = histories.CommitListContainer;
55+
if (list == null)
56+
return;
57+
58+
// Calculate drawing area.
59+
double width = Bounds.Width - 273 - histories.AuthorNameColumnWidth.Value;
60+
double height = Bounds.Height;
61+
double startY = list.Scroll?.Offset.Y ?? 0;
62+
double endY = startY + height + 28;
63+
64+
// Apply scroll offset and clip.
65+
using (context.PushClip(new Rect(0, 0, width, height)))
66+
using (context.PushTransform(Matrix.CreateTranslation(0, -startY)))
67+
{
68+
// Draw contents
69+
DrawCurves(context, graph, startY, endY);
70+
DrawAnchors(context, graph, startY, endY);
71+
}
72+
}
73+
74+
private void DrawCurves(DrawingContext context, Models.CommitGraph graph, double top, double bottom)
75+
{
76+
var grayedPen = new Pen(new SolidColorBrush(Colors.Gray, 0.4), Models.CommitGraph.Pens[0].Thickness);
77+
var onlyHighlightCurrentBranch = OnlyHighlightCurrentBranch;
78+
79+
if (onlyHighlightCurrentBranch)
80+
{
81+
foreach (var link in graph.Links)
82+
{
83+
if (link.IsMerged)
84+
continue;
85+
if (link.End.Y < top)
86+
continue;
87+
if (link.Start.Y > bottom)
88+
break;
89+
90+
var geo = new StreamGeometry();
91+
using (var ctx = geo.Open())
92+
{
93+
ctx.BeginFigure(link.Start, false);
94+
ctx.QuadraticBezierTo(link.Control, link.End);
95+
}
96+
97+
context.DrawGeometry(null, grayedPen, geo);
98+
}
99+
}
100+
101+
foreach (var line in graph.Paths)
102+
{
103+
var last = line.Points[0];
104+
var size = line.Points.Count;
105+
106+
if (line.Points[size - 1].Y < top)
107+
continue;
108+
if (last.Y > bottom)
109+
break;
110+
111+
var geo = new StreamGeometry();
112+
var pen = Models.CommitGraph.Pens[line.Color];
113+
114+
using (var ctx = geo.Open())
115+
{
116+
var started = false;
117+
var ended = false;
118+
for (int i = 1; i < size; i++)
119+
{
120+
var cur = line.Points[i];
121+
if (cur.Y < top)
122+
{
123+
last = cur;
124+
continue;
125+
}
126+
127+
if (!started)
128+
{
129+
ctx.BeginFigure(last, false);
130+
started = true;
131+
}
132+
133+
if (cur.Y > bottom)
134+
{
135+
cur = new Point(cur.X, bottom);
136+
ended = true;
137+
}
138+
139+
if (cur.X > last.X)
140+
{
141+
ctx.QuadraticBezierTo(new Point(cur.X, last.Y), cur);
142+
}
143+
else if (cur.X < last.X)
144+
{
145+
if (i < size - 1)
146+
{
147+
var midY = (last.Y + cur.Y) / 2;
148+
ctx.CubicBezierTo(new Point(last.X, midY + 4), new Point(cur.X, midY - 4), cur);
149+
}
150+
else
151+
{
152+
ctx.QuadraticBezierTo(new Point(last.X, cur.Y), cur);
153+
}
154+
}
155+
else
156+
{
157+
ctx.LineTo(cur);
158+
}
159+
160+
if (ended)
161+
break;
162+
last = cur;
163+
}
164+
}
165+
166+
if (!line.IsMerged && onlyHighlightCurrentBranch)
167+
context.DrawGeometry(null, grayedPen, geo);
168+
else
169+
context.DrawGeometry(null, pen, geo);
170+
}
171+
172+
foreach (var link in graph.Links)
173+
{
174+
if (onlyHighlightCurrentBranch && !link.IsMerged)
175+
continue;
176+
if (link.End.Y < top)
177+
continue;
178+
if (link.Start.Y > bottom)
179+
break;
180+
181+
var geo = new StreamGeometry();
182+
using (var ctx = geo.Open())
183+
{
184+
ctx.BeginFigure(link.Start, false);
185+
ctx.QuadraticBezierTo(link.Control, link.End);
186+
}
187+
188+
context.DrawGeometry(null, Models.CommitGraph.Pens[link.Color], geo);
189+
}
190+
}
191+
192+
private void DrawAnchors(DrawingContext context, Models.CommitGraph graph, double top, double bottom)
193+
{
194+
var dotFill = DotBrush;
195+
var dotFillPen = new Pen(dotFill, 2);
196+
var grayedPen = new Pen(Brushes.Gray, Models.CommitGraph.Pens[0].Thickness);
197+
var onlyHighlightCurrentBranch = OnlyHighlightCurrentBranch;
198+
199+
foreach (var dot in graph.Dots)
200+
{
201+
if (dot.Center.Y < top)
202+
continue;
203+
if (dot.Center.Y > bottom)
204+
break;
205+
206+
var pen = Models.CommitGraph.Pens[dot.Color];
207+
if (!dot.IsMerged && onlyHighlightCurrentBranch)
208+
pen = grayedPen;
209+
210+
switch (dot.Type)
211+
{
212+
case Models.CommitGraph.DotType.Head:
213+
context.DrawEllipse(dotFill, pen, dot.Center, 6, 6);
214+
context.DrawEllipse(pen.Brush, null, dot.Center, 3, 3);
215+
break;
216+
case Models.CommitGraph.DotType.Merge:
217+
context.DrawEllipse(pen.Brush, null, dot.Center, 6, 6);
218+
context.DrawLine(dotFillPen, new Point(dot.Center.X, dot.Center.Y - 3), new Point(dot.Center.X, dot.Center.Y + 3));
219+
context.DrawLine(dotFillPen, new Point(dot.Center.X - 3, dot.Center.Y), new Point(dot.Center.X + 3, dot.Center.Y));
220+
break;
221+
default:
222+
context.DrawEllipse(dotFill, pen, dot.Center, 3, 3);
223+
break;
224+
}
225+
}
226+
}
227+
}
228+
}

src/Views/CommitStatusIndicator.cs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System;
2+
3+
using Avalonia;
4+
using Avalonia.Controls;
5+
using Avalonia.Media;
6+
7+
namespace SourceGit.Views
8+
{
9+
public class CommitStatusIndicator : Control
10+
{
11+
public static readonly StyledProperty<Models.Branch> CurrentBranchProperty =
12+
AvaloniaProperty.Register<CommitStatusIndicator, Models.Branch>(nameof(CurrentBranch));
13+
14+
public Models.Branch CurrentBranch
15+
{
16+
get => GetValue(CurrentBranchProperty);
17+
set => SetValue(CurrentBranchProperty, value);
18+
}
19+
20+
public static readonly StyledProperty<IBrush> AheadBrushProperty =
21+
AvaloniaProperty.Register<CommitStatusIndicator, IBrush>(nameof(AheadBrush));
22+
23+
public IBrush AheadBrush
24+
{
25+
get => GetValue(AheadBrushProperty);
26+
set => SetValue(AheadBrushProperty, value);
27+
}
28+
29+
public static readonly StyledProperty<IBrush> BehindBrushProperty =
30+
AvaloniaProperty.Register<CommitStatusIndicator, IBrush>(nameof(BehindBrush));
31+
32+
public IBrush BehindBrush
33+
{
34+
get => GetValue(BehindBrushProperty);
35+
set => SetValue(BehindBrushProperty, value);
36+
}
37+
38+
enum Status
39+
{
40+
Normal,
41+
Ahead,
42+
Behind,
43+
}
44+
45+
public override void Render(DrawingContext context)
46+
{
47+
if (_status == Status.Normal)
48+
return;
49+
50+
context.DrawEllipse(_status == Status.Ahead ? AheadBrush : BehindBrush, null, new Rect(0, 0, 5, 5));
51+
}
52+
53+
protected override Size MeasureOverride(Size availableSize)
54+
{
55+
if (DataContext is Models.Commit commit && CurrentBranch is not null)
56+
{
57+
var sha = commit.SHA;
58+
var track = CurrentBranch.TrackStatus;
59+
60+
if (track.Ahead.Contains(sha))
61+
_status = Status.Ahead;
62+
else if (track.Behind.Contains(sha))
63+
_status = Status.Behind;
64+
else
65+
_status = Status.Normal;
66+
}
67+
else
68+
{
69+
_status = Status.Normal;
70+
}
71+
72+
return _status == Status.Normal ? new Size(0, 0) : new Size(9, 5);
73+
}
74+
75+
protected override void OnDataContextChanged(EventArgs e)
76+
{
77+
base.OnDataContextChanged(e);
78+
InvalidateMeasure();
79+
}
80+
81+
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
82+
{
83+
base.OnPropertyChanged(change);
84+
if (change.Property == CurrentBranchProperty)
85+
InvalidateMeasure();
86+
}
87+
88+
private Status _status = Status.Normal;
89+
}
90+
}

0 commit comments

Comments
 (0)