Skip to content
This repository was archived by the owner on Dec 5, 2024. It is now read-only.

Commit f7acb86

Browse files
Managing scroll and maintaining selected index in HistoryControl
1 parent e4b68dc commit f7acb86

File tree

1 file changed

+144
-58
lines changed

1 file changed

+144
-58
lines changed

src/UnityExtension/Assets/Editor/GitHub.Unity/UI/HistoryView.cs

Lines changed: 144 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -6,75 +6,86 @@
66

77
namespace GitHub.Unity
88
{
9-
struct HistoryControlRenderResult
10-
{
11-
public Rect Rect;
12-
public bool RequiresRepaint;
13-
}
14-
159
[Serializable]
1610
class HistoryControl
1711
{
1812
private const string HistoryEntryDetailFormat = "{0} {1}";
1913

14+
[SerializeField] private Vector2 scroll;
2015
[SerializeField] private List<GitLogEntry> entries = new List<GitLogEntry>();
2116
[SerializeField] private int statusAhead;
22-
[SerializeField] private int selectedIndex;
17+
[SerializeField] private int selectedIndex = -1;
2318

2419
[NonSerialized] private Action<GitLogEntry> rightClickNextRender;
2520
[NonSerialized] private GitLogEntry rightClickNextRenderEntry;
2621
[NonSerialized] private int controlId;
2722

28-
public HistoryControlRenderResult Render(Rect containingRect, Rect rect, Vector2 scroll, Action<GitLogEntry> singleClick = null,
23+
public int SelectedIndex
24+
{
25+
get { return selectedIndex; }
26+
set { selectedIndex = value; }
27+
}
28+
29+
public GitLogEntry SelectedGitLogEntry
30+
{
31+
get { return SelectedIndex < 0 ? GitLogEntry.Default : entries[SelectedIndex]; }
32+
}
33+
34+
public bool Render(Rect containingRect, Action<GitLogEntry> singleClick = null,
2935
Action<GitLogEntry> doubleClick = null, Action<GitLogEntry> rightClick = null)
3036
{
3137
var requiresRepaint = false;
38+
var rect = Rect.zero;
3239

33-
controlId = GUIUtility.GetControlID(FocusType.Keyboard);
34-
35-
if (Event.current.type != EventType.Repaint)
40+
scroll = GUILayout.BeginScrollView(scroll);
3641
{
37-
if (rightClickNextRender != null)
42+
controlId = GUIUtility.GetControlID(FocusType.Keyboard);
43+
44+
if (Event.current.type != EventType.Repaint)
3845
{
39-
rightClickNextRender.Invoke(rightClickNextRenderEntry);
40-
rightClickNextRender = null;
41-
rightClickNextRenderEntry = GitLogEntry.Default;
46+
if (rightClickNextRender != null)
47+
{
48+
rightClickNextRender.Invoke(rightClickNextRenderEntry);
49+
rightClickNextRender = null;
50+
rightClickNextRenderEntry = GitLogEntry.Default;
51+
}
4252
}
43-
}
4453

45-
var startDisplay = scroll.y;
46-
var endDisplay = scroll.y + containingRect.height;
54+
var startDisplay = scroll.y;
55+
var endDisplay = scroll.y + containingRect.height;
4756

48-
rect = new Rect(rect.x, rect.y, rect.width, 0);
57+
rect = new Rect(containingRect.x, containingRect.y, containingRect.width, 0);
4958

50-
for (var index = 0; index < entries.Count; index++)
51-
{
52-
var entry = entries[index];
59+
for (var index = 0; index < entries.Count; index++)
60+
{
61+
var entry = entries[index];
5362

54-
var entryRect = new Rect(rect.x, rect.y, rect.width, Styles.HistoryEntryHeight);
63+
var entryRect = new Rect(rect.x, rect.y, rect.width, Styles.HistoryEntryHeight);
5564

56-
var shouldRenderEntry = !(entryRect.y > endDisplay || entryRect.yMax < startDisplay);
57-
if (shouldRenderEntry && Event.current.type == EventType.Repaint)
58-
{
59-
RenderEntry(entryRect, entry, index);
60-
}
65+
var shouldRenderEntry = !(entryRect.y > endDisplay || entryRect.yMax < startDisplay);
66+
if (shouldRenderEntry && Event.current.type == EventType.Repaint)
67+
{
68+
RenderEntry(entryRect, entry, index);
69+
}
6170

62-
var entryRequiresRepaint = HandleInput(entryRect, entry, index, singleClick, doubleClick, rightClick);
63-
requiresRepaint = requiresRepaint || entryRequiresRepaint;
71+
var entryRequiresRepaint = HandleInput(entryRect, entry, index, singleClick, doubleClick, rightClick);
72+
requiresRepaint = requiresRepaint || entryRequiresRepaint;
6473

65-
rect.y += Styles.HistoryEntryHeight;
74+
rect.y += Styles.HistoryEntryHeight;
75+
}
6676
}
6777

68-
return new HistoryControlRenderResult {
69-
Rect = rect,
70-
RequiresRepaint = requiresRepaint
71-
};
78+
GUILayout.Space(rect.y - containingRect.y);
79+
80+
GUILayout.EndScrollView();
81+
82+
return requiresRepaint;
7283
}
7384

7485
private void RenderEntry(Rect entryRect, GitLogEntry entry, int index)
7586
{
7687
var isLocalCommit = index < statusAhead;
77-
var isSelected = index == selectedIndex;
88+
var isSelected = index == SelectedIndex;
7889
var summaryRect = new Rect(entryRect.x, entryRect.y + Styles.BaseSpacing / 2, entryRect.width, Styles.HistorySummaryHeight + Styles.BaseSpacing);
7990
var timestampRect = new Rect(entryRect.x, entryRect.yMax - Styles.HistoryDetailsHeight - Styles.BaseSpacing / 2, entryRect.width, Styles.HistoryDetailsHeight);
8091

@@ -139,7 +150,7 @@ private bool HandleInput(Rect rect, GitLogEntry entry, int index, Action<GitLogE
139150
Event.current.Use();
140151
GUIUtility.keyboardControl = controlId;
141152

142-
selectedIndex = index;
153+
SelectedIndex = index;
143154
requiresRepaint = true;
144155
var clickCount = Event.current.clickCount;
145156
var mouseButton = Event.current.button;
@@ -160,7 +171,7 @@ private bool HandleInput(Rect rect, GitLogEntry entry, int index, Action<GitLogE
160171
}
161172

162173
// Keyboard navigation if this child is the current selection
163-
if (GUIUtility.keyboardControl == controlId && index == selectedIndex && Event.current.type == EventType.KeyDown)
174+
if (GUIUtility.keyboardControl == controlId && index == SelectedIndex && Event.current.type == EventType.KeyDown)
164175
{
165176
var directionY = Event.current.keyCode == KeyCode.UpArrow ? -1 : Event.current.keyCode == KeyCode.DownArrow ? 1 : 0;
166177
if (directionY != 0)
@@ -213,8 +224,27 @@ private void DrawTimelineRectAroundIconRect(Rect parentRect, Rect iconRect)
213224

214225
public void Load(int loadAhead, List<GitLogEntry> loadEntries)
215226
{
227+
var selectedCommitId = SelectedGitLogEntry.CommitID;
228+
216229
statusAhead = loadAhead;
217230
entries = loadEntries;
231+
232+
var changed = false;
233+
for (var index = 0; index < entries.Count; index++)
234+
{
235+
var gitLogEntry = entries[index];
236+
if (gitLogEntry.CommitID.Equals(selectedCommitId))
237+
{
238+
selectedIndex = index;
239+
changed = true;
240+
break;
241+
}
242+
}
243+
244+
if (!changed)
245+
{
246+
selectedIndex = -1;
247+
}
218248
}
219249

220250
private int SelectNext(int index)
@@ -223,7 +253,7 @@ private int SelectNext(int index)
223253

224254
if (index < entries.Count)
225255
{
226-
selectedIndex = index;
256+
SelectedIndex = index;
227257
}
228258
else
229259
{
@@ -239,15 +269,20 @@ private int SelectPrevious(int index)
239269

240270
if (index >= 0)
241271
{
242-
selectedIndex = index;
272+
SelectedIndex = index;
243273
}
244274
else
245275
{
246-
selectedIndex = -1;
276+
SelectedIndex = -1;
247277
}
248278

249279
return index;
250280
}
281+
282+
public void ScrollTo(int index)
283+
{
284+
scroll.Set(scroll.x, Styles.HistoryEntryHeight * index);
285+
}
251286
}
252287

253288
enum LogEntryState
@@ -286,8 +321,10 @@ class HistoryView : Subview
286321
[SerializeField] private bool hasRemote;
287322
[SerializeField] private string currentRemoteName;
288323

289-
[SerializeField] private Vector2 historyScroll;
290324
[SerializeField] private HistoryControl historyControl;
325+
[SerializeField] private GitLogEntry selectedEntry = GitLogEntry.Default;
326+
327+
[SerializeField] private Vector2 detailsScroll;
291328

292329
[SerializeField] private List<GitLogEntry> logEntries = new List<GitLogEntry>();
293330

@@ -393,30 +430,74 @@ public void OnEmbeddedGUI()
393430
GUILayout.EndHorizontal();
394431

395432
var rect = GUILayoutUtility.GetLastRect();
396-
historyScroll = GUILayout.BeginScrollView(historyScroll);
397-
{
398-
OnHistoryGUI(new Rect(0f, 0f, Position.width, Position.height - rect.height));
399-
}
400-
GUILayout.EndScrollView();
401-
}
402-
403-
private void OnHistoryGUI(Rect rect)
404-
{
405-
var initialRect = rect;
406433
if (historyControl != null)
407434
{
408-
var renderResult = historyControl.Render(initialRect, rect, historyScroll,
409-
entry => { },
435+
var historyControlRect = new Rect(0f, 0f, Position.width, Position.height - rect.height);
436+
437+
var requiresRepaint = historyControl.Render(historyControlRect,
438+
entry => {
439+
selectedEntry = entry;
440+
},
410441
entry => { },
411442
entry => { });
412443

413-
rect = renderResult.Rect;
414-
415-
if (renderResult.RequiresRepaint)
444+
if (requiresRepaint)
416445
Redraw();
417446
}
418447

419-
GUILayout.Space(rect.y - initialRect.y);
448+
if (!selectedEntry.Equals(GitLogEntry.Default))
449+
{
450+
// Top bar for scrolling to selection or clearing it
451+
GUILayout.BeginHorizontal(EditorStyles.toolbar);
452+
{
453+
if (GUILayout.Button(CommitDetailsTitle, Styles.HistoryToolbarButtonStyle))
454+
{
455+
historyControl.ScrollTo(historyControl.SelectedIndex);
456+
}
457+
if (GUILayout.Button(ClearSelectionButton, Styles.HistoryToolbarButtonStyle, GUILayout.ExpandWidth(false)))
458+
{
459+
selectedEntry = GitLogEntry.Default;
460+
historyControl.SelectedIndex = -1;
461+
}
462+
}
463+
GUILayout.EndHorizontal();
464+
465+
// Log entry details - including changeset tree (if any changes are found)
466+
detailsScroll = GUILayout.BeginScrollView(detailsScroll, GUILayout.Height(250));
467+
{
468+
HistoryDetailsEntry(selectedEntry);
469+
470+
GUILayout.Space(EditorGUIUtility.standardVerticalSpacing);
471+
GUILayout.Label("Files changed", EditorStyles.boldLabel);
472+
GUILayout.Space(-5);
473+
474+
GUILayout.BeginHorizontal(Styles.HistoryFileTreeBoxStyle);
475+
{
476+
//changesetTree.OnGUI();
477+
}
478+
GUILayout.EndHorizontal();
479+
480+
GUILayout.Space(EditorGUIUtility.standardVerticalSpacing);
481+
}
482+
GUILayout.EndScrollView();
483+
}
484+
}
485+
486+
private void HistoryDetailsEntry(GitLogEntry entry)
487+
{
488+
GUILayout.BeginVertical(Styles.HeaderBoxStyle);
489+
GUILayout.Label(entry.Summary, Styles.HistoryDetailsTitleStyle, GUILayout.Width(Position.width));
490+
491+
GUILayout.Space(-5);
492+
493+
GUILayout.BeginHorizontal();
494+
GUILayout.Label(entry.PrettyTimeString, Styles.HistoryDetailsMetaInfoStyle);
495+
GUILayout.Label(entry.AuthorName, Styles.HistoryDetailsMetaInfoStyle);
496+
GUILayout.FlexibleSpace();
497+
GUILayout.EndHorizontal();
498+
499+
GUILayout.Space(3);
500+
GUILayout.EndVertical();
420501
}
421502

422503
private void RepositoryTrackingOnStatusChanged(CacheUpdateEvent cacheUpdateEvent)
@@ -519,6 +600,11 @@ private void BuildHistoryControl()
519600
}
520601

521602
historyControl.Load(statusAhead, logEntries);
603+
if (!selectedEntry.Equals(GitLogEntry.Default)
604+
&& selectedEntry.CommitID != historyControl.SelectedGitLogEntry.CommitID)
605+
{
606+
selectedEntry = GitLogEntry.Default;
607+
}
522608
}
523609

524610
private void Pull()

0 commit comments

Comments
 (0)