1- using System . Collections . Generic ;
2- using System . Linq ;
3- using System ;
4- using UnityEngine ;
1+ using System ;
52using UnityEditor ;
3+ using UnityEngine ;
64
75namespace GitHub . Unity
86{
97 public class FileHistoryWindow : BaseWindow
108 {
9+ private const string Title = "File History" ;
10+
11+ [ NonSerialized ] private bool firstOnGUI = true ;
12+
13+ [ SerializeField ] private bool locked ;
1114 [ SerializeField ] private string assetPath ;
12- [ SerializeField ] private List < GitLogEntry > history ;
13- [ SerializeField ] private Vector2 scroll ;
14- [ SerializeField ] private Vector2 detailsScroll ;
15- [ NonSerialized ] private bool busy ;
16- [ SerializeField ] private HistoryControl historyControl ;
17- [ SerializeField ] private GitLogEntry selectedEntry = GitLogEntry . Default ;
18- [ SerializeField ] private ChangesTree treeChanges = new ChangesTree { IsSelectable = false , DisplayRootNode = false } ;
15+ [ SerializeField ] private FileHistoryView fileHistoryView = new FileHistoryView ( ) ;
1916
20- public static FileHistoryWindow OpenWindow ( string assetPath )
17+ public static FileHistoryWindow OpenWindow ( IApplicationManager applicationManager , string assetPath )
2118 {
22- var popupWindow = CreateInstance < FileHistoryWindow > ( ) ;
19+ var fileHistoryWindow = CreateInstance < FileHistoryWindow > ( ) ;
20+ fileHistoryWindow . InitializeWindow ( applicationManager ) ;
2321
24- popupWindow . titleContent = new GUIContent ( assetPath + " History" ) ;
25- popupWindow . Open ( assetPath ) ;
22+ fileHistoryWindow . Open ( assetPath ) ;
23+ fileHistoryWindow . Show ( ) ;
2624
27- popupWindow . Show ( ) ;
25+ return fileHistoryWindow ;
26+ }
2827
29- return popupWindow ;
28+ public void Open ( string path )
29+ {
30+ assetPath = path ;
31+ fileHistoryView . SetPath ( path ) ;
3032 }
3133
32- public override bool IsBusy { get { return this . busy ; } }
34+ public override void Initialize ( IApplicationManager applicationManager )
35+ {
36+ base . Initialize ( applicationManager ) ;
3337
34- public void Open ( string assetPath )
38+ fileHistoryView . InitializeView ( this ) ;
39+ }
40+
41+ public override bool IsBusy
3542 {
36- this . assetPath = assetPath ;
43+ get { return false ; }
44+ }
3745
38- this . RefreshLog ( ) ;
46+ public override void OnEnable ( )
47+ {
48+ base . OnEnable ( ) ;
49+
50+ if ( fileHistoryView != null )
51+ fileHistoryView . OnEnable ( ) ;
3952 }
4053
41- public void RefreshLog ( )
54+ public override void OnDisable ( )
4255 {
43- var path = Application . dataPath . ToNPath ( ) . Parent . Combine ( assetPath . ToNPath ( ) ) ;
44- this . busy = true ;
45- this . GitClient . LogFile ( path ) . ThenInUI ( ( success , logEntries ) => {
46- this . history = logEntries ;
47- this . BuildHistoryControl ( ) ;
48- this . Repaint ( ) ;
49- this . busy = false ;
50- } ) . Start ( ) ;
56+ base . OnDisable ( ) ;
57+ if ( fileHistoryView != null )
58+ fileHistoryView . OnDisable ( ) ;
5159 }
5260
53- private void CheckoutVersion ( string commitID )
61+ public override void OnDataUpdate ( )
5462 {
55- this . busy = true ;
56- this . GitClient . CheckoutVersion ( commitID , new string [ ] { assetPath } ) . ThenInUI ( ( success , result ) => {
57- AssetDatabase . Refresh ( ) ;
58- this . busy = false ;
59- } ) . Start ( ) ;
63+ base . OnDataUpdate ( ) ;
64+ MaybeUpdateData ( ) ;
65+
66+ if ( fileHistoryView != null )
67+ fileHistoryView . OnDataUpdate ( ) ;
6068 }
6169
62- private void Checkout ( )
70+ public override void OnFocusChanged ( )
6371 {
64- // TODO: This is a destructive, irreversible operation; we should prompt user if
65- // there are any changes to the file
66- this . CheckoutVersion ( this . selectedEntry . CommitID ) ;
72+ if ( fileHistoryView != null )
73+ fileHistoryView . OnFocusChanged ( ) ;
6774 }
6875
69- public override void OnUI ( )
76+ public override void OnRepositoryChanged ( IRepository oldRepository )
7077 {
71- // TODO:
72- // - should handle case where the file is outside of the repository (handle exceptional cases)
73- // - should display a spinner while history is still loading...
74- base . OnUI ( ) ;
75- GUILayout . BeginHorizontal ( Styles . HeaderStyle ) ;
78+ base . OnRepositoryChanged ( oldRepository ) ;
79+
80+ DetachHandlers ( oldRepository ) ;
81+ AttachHandlers ( Repository ) ;
82+
83+ if ( HasRepository )
7684 {
77- GUILayout . Label ( "GIT File History for: " , Styles . BoldLabel ) ;
78- if ( HyperlinkLabel ( this . assetPath ) )
79- {
80- var asset = AssetDatabase . LoadMainAssetAtPath ( this . assetPath ) ;
81- Selection . activeObject = asset ;
82- EditorGUIUtility . PingObject ( asset ) ;
83- }
84- GUILayout . FlexibleSpace ( ) ;
85+
8586 }
86- GUILayout . EndHorizontal ( ) ;
87-
88- if ( historyControl != null )
87+ else
8988 {
90- var rect = GUILayoutUtility . GetLastRect ( ) ;
91- var historyControlRect = new Rect ( 0f , 0f , Position . width , Position . height - rect . height ) ;
92-
93- var requiresRepaint = historyControl . Render ( historyControlRect ,
94- entry => {
95- selectedEntry = entry ;
96- BuildTree ( ) ;
97- } ,
98- entry => { } , entry => {
99- GenericMenu menu = new GenericMenu ( ) ;
100- menu . AddItem ( new GUIContent ( "Checkout version " + entry . ShortID ) , false , Checkout ) ;
101- menu . ShowAsContext ( ) ;
102- } ) ;
103-
104- if ( requiresRepaint )
105- Redraw ( ) ;
89+
10690 }
91+ }
10792
108- // DrawDetails is maybe irrelevant? Would be a nice place to put the short id perhaps?
109- DrawDetails ( ) ;
93+ public override void OnSelectionChange ( )
94+ {
95+ base . OnSelectionChange ( ) ;
96+ if ( fileHistoryView != null )
97+ fileHistoryView . OnSelectionChange ( ) ;
11098 }
11199
112- private bool HyperlinkLabel ( string label )
100+ public override void Refresh ( )
113101 {
114- bool returnValue = false ;
115- if ( GUILayout . Button ( label , HyperlinkStyle ) )
116- {
117- returnValue = true ;
118- }
119- var rect = GUILayoutUtility . GetLastRect ( ) ;
120- var size = HyperlinkStyle . CalcSize ( new GUIContent ( label ) ) ;
121- rect . width = size . x ;
122- EditorGUIUtility . AddCursorRect ( rect , MouseCursor . Link ) ;
123- return returnValue ;
102+ base . Refresh ( ) ;
103+ if ( fileHistoryView != null )
104+ fileHistoryView . Refresh ( ) ;
105+ Refresh ( CacheType . GitLocks ) ;
106+ Redraw ( ) ;
124107 }
125108
126- private void BuildHistoryControl ( )
109+ public override void OnUI ( )
127110 {
128- if ( historyControl == null )
129- {
130- historyControl = new HistoryControl ( ) ;
131- }
111+ base . OnUI ( ) ;
132112
133- historyControl . Load ( 0 , this . history ) ;
113+ fileHistoryView . OnGUI ( ) ;
134114 }
135115
136- private const string CommitDetailsTitle = "Commit details" ;
137- private const string ClearSelectionButton = "×" ;
138-
139- private void DrawDetails ( )
116+ private void MaybeUpdateData ( )
140117 {
141- if ( ! selectedEntry . Equals ( GitLogEntry . Default ) )
118+ if ( firstOnGUI )
142119 {
143- // Top bar for scrolling to selection or clearing it
144- GUILayout . BeginHorizontal ( EditorStyles . toolbar ) ;
145- {
146- if ( GUILayout . Button ( CommitDetailsTitle , Styles . ToolbarButtonStyle ) )
147- {
148- historyControl . ScrollTo ( historyControl . SelectedIndex ) ;
149- }
150- if ( GUILayout . Button ( ClearSelectionButton , Styles . ToolbarButtonStyle , GUILayout . ExpandWidth ( false ) ) )
151- {
152- selectedEntry = GitLogEntry . Default ;
153- historyControl . SelectedIndex = - 1 ;
154- }
155- }
156- GUILayout . EndHorizontal ( ) ;
157-
158- // Log entry details - including changeset tree (if any changes are found)
159- detailsScroll = GUILayout . BeginScrollView ( detailsScroll , GUILayout . Height ( 250 ) ) ;
160- {
161- HistoryDetailsEntry ( selectedEntry ) ;
162-
163- GUILayout . Space ( EditorGUIUtility . standardVerticalSpacing ) ;
164- GUILayout . Label ( "Files changed" , EditorStyles . boldLabel ) ;
165- GUILayout . Space ( - 5 ) ;
166-
167- var rect = GUILayoutUtility . GetLastRect ( ) ;
168- GUILayout . BeginHorizontal ( Styles . HistoryFileTreeBoxStyle ) ;
169- GUILayout . BeginVertical ( ) ;
170- {
171- var borderLeft = Styles . Label . margin . left ;
172- var treeControlRect = new Rect ( rect . x + borderLeft , rect . y , Position . width - borderLeft * 2 , Position . height - rect . height + Styles . CommitAreaPadding ) ;
173- var treeRect = new Rect ( 0f , 0f , 0f , 0f ) ;
174- if ( treeChanges != null )
175- {
176- treeChanges . FolderStyle = Styles . Foldout ;
177- treeChanges . TreeNodeStyle = Styles . TreeNode ;
178- treeChanges . ActiveTreeNodeStyle = Styles . ActiveTreeNode ;
179- treeChanges . FocusedTreeNodeStyle = Styles . FocusedTreeNode ;
180- treeChanges . FocusedActiveTreeNodeStyle = Styles . FocusedActiveTreeNode ;
181-
182- treeRect = treeChanges . Render ( treeControlRect , detailsScroll ,
183- node => {
184- } ,
185- node => {
186- } ,
187- node => {
188- } ) ;
189-
190- if ( treeChanges . RequiresRepaint )
191- Redraw ( ) ;
192- }
193-
194- GUILayout . Space ( treeRect . y - treeControlRect . y ) ;
195- }
196- GUILayout . EndVertical ( ) ;
197- GUILayout . EndHorizontal ( ) ;
198-
199- GUILayout . Space ( EditorGUIUtility . standardVerticalSpacing ) ;
200- }
201- GUILayout . EndScrollView ( ) ;
120+ titleContent = new GUIContent ( Title , Styles . SmallLogo ) ;
202121 }
122+ firstOnGUI = false ;
203123 }
204124
205- private void HistoryDetailsEntry ( GitLogEntry entry )
125+ private void AttachHandlers ( IRepository repository )
206126 {
207- GUILayout . BeginVertical ( Styles . HeaderBoxStyle ) ;
208- GUILayout . Label ( entry . Summary , Styles . HistoryDetailsTitleStyle ) ;
209-
210- GUILayout . Space ( - 5 ) ;
211-
212- GUILayout . BeginHorizontal ( ) ;
213- GUILayout . Label ( entry . PrettyTimeString , Styles . HistoryDetailsMetaInfoStyle ) ;
214- GUILayout . Label ( entry . AuthorName , Styles . HistoryDetailsMetaInfoStyle ) ;
215- GUILayout . FlexibleSpace ( ) ;
216- GUILayout . EndHorizontal ( ) ;
217-
218- GUILayout . Space ( 3 ) ;
219- GUILayout . EndVertical ( ) ;
127+ if ( repository == null )
128+ return ;
220129 }
221130
222- private void BuildTree ( )
131+ private void DetachHandlers ( IRepository repository )
223132 {
224- treeChanges . PathSeparator = Environment . FileSystem . DirectorySeparatorChar . ToString ( ) ;
225- treeChanges . Load ( selectedEntry . changes . Select ( entry => new GitStatusEntryTreeData ( entry ) ) ) ;
226- Redraw ( ) ;
133+ if ( repository == null )
134+ return ;
227135 }
228136
229- protected static GUIStyle hyperlinkStyle = null ;
230-
231- public static GUIStyle HyperlinkStyle
137+ private void ShowButton ( Rect rect )
232138 {
233- get
234- {
235- if ( hyperlinkStyle == null )
236- {
237- hyperlinkStyle = new GUIStyle ( EditorStyles . wordWrappedLabel ) ;
238- hyperlinkStyle . normal . textColor = new Color ( 95.0f / 255.0f , 170.0f / 255.0f , 247.0f / 255.0f ) ;
239- }
240- return hyperlinkStyle ;
241- }
242- }
139+ EditorGUI . BeginChangeCheck ( ) ;
140+
141+ locked = GUI . Toggle ( rect , locked , GUIContent . none , Styles . LockButtonStyle ) ;
142+
143+ if ( ! EditorGUI . EndChangeCheck ( ) )
144+ return ;
145+
146+ this . OnSelectionChange ( ) ;
147+ }
243148 }
244- }
149+ }
0 commit comments