66
77namespace 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