Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 325 lines (268 sloc) 10.105 kb
d6a0b1b @pieter Use a separate controller for tabs
pieter authored
1 //
708c08a @pieter First part of splitting views
pieter authored
2 // PBGitHistoryView.m
d6a0b1b @pieter Use a separate controller for tabs
pieter authored
3 // GitX
4 //
708c08a @pieter First part of splitting views
pieter authored
5 // Created by Pieter de Bie on 19-09-08.
d6a0b1b @pieter Use a separate controller for tabs
pieter authored
6 // Copyright 2008 __MyCompanyName__. All rights reserved.
7 //
8
708c08a @pieter First part of splitting views
pieter authored
9 #import "PBGitHistoryController.h"
28e8bac @pieter Add QuickLook support in tree view
pieter authored
10 #import "CWQuickLook.h"
ce37b09 @ciaran Merge commit 'pieter/master' into grapher
ciaran authored
11 #import "PBGitGrapher.h"
d8068b1 @pieter Don't display graph if there's a search or a sort
pieter authored
12 #import "PBGitRevisionCell.h"
4cefe8e @pieter HistoryView: Allow dragging of refs to move them
pieter authored
13 #import "PBCommitList.h"
28e8bac @pieter Add QuickLook support in tree view
pieter authored
14 #define QLPreviewPanel NSClassFromString(@"QLPreviewPanel")
d6a0b1b @pieter Use a separate controller for tabs
pieter authored
15
16
708c08a @pieter First part of splitting views
pieter authored
17 @implementation PBGitHistoryController
53dfea5 @pieter PBViewController: Extract common code to a superclass
pieter authored
18 @synthesize selectedTab, webCommit, rawCommit, gitTree, commitController;
d6a0b1b @pieter Use a separate controller for tabs
pieter authored
19
01a5cf3 @ciaran awakeFromNib should be void
ciaran authored
20 - (void)awakeFromNib
d6a0b1b @pieter Use a separate controller for tabs
pieter authored
21 {
8de6a10 @ciaran Remember the currently selected tab across sessions.
ciaran authored
22 self.selectedTab = [[NSUserDefaults standardUserDefaults] integerForKey:@"Repository Window Selected Tab Index"];;
6ba944b @pieter Implement a DetailsController
pieter authored
23 [commitController addObserver:self forKeyPath:@"selection" options:(NSKeyValueObservingOptionNew,NSKeyValueObservingOptionOld) context:@"commitChange"];
28e8bac @pieter Add QuickLook support in tree view
pieter authored
24 [treeController addObserver:self forKeyPath:@"selection" options:0 context:@"treeChange"];
0d0a83f @pieter HistoryView: Reset the sorting after selecting another branch
pieter authored
25 [repository addObserver:self forKeyPath:@"currentBranch" options:0 context:@"branchChange"];
c1e701a @ciaran Remove the horizontal spacing between the rows in the commit list tablev...
ciaran authored
26 NSSize cellSpacing = [commitList intercellSpacing];
27 cellSpacing.height = 0;
28 [commitList setIntercellSpacing:cellSpacing];
708c08a @pieter First part of splitting views
pieter authored
29 [fileBrowser setTarget:self];
30 [fileBrowser setDoubleAction:@selector(openSelectedFile:)];
a2217fe @pieter Reload commits after doing a commit
pieter authored
31
a62e14f @pieter HistoryView: Remove the BranchController
pieter authored
32 if (!repository.currentBranch) {
a2217fe @pieter Reload commits after doing a commit
pieter authored
33 [repository reloadRefs];
34 [repository readCurrentBranch];
35 }
36 else
37 [repository lazyReload];
e329493 @pieter Move toolbar to view xib
pieter authored
38
4963175 @pieter HistoryView: Allow sorting on commit subject
pieter authored
39 // Set a sort descriptor for the subject column in the history list, as
40 // It can't be sorted by default (because it's bound to a PBGitCommit)
41 [[commitList tableColumnWithIdentifier:@"subject"] setSortDescriptorPrototype:[[NSSortDescriptor alloc] initWithKey:@"subject" ascending:YES]];
8273aec Allow a user to select which columns to display
Pieter de Bie authored
42 // Add a menu that allows a user to select which columns to view
43 [[commitList headerView] setMenu:[self tableColumnMenu]];
d669050 @heipei Add PBCollapsibleSplitView as subclass of PBNiceSplitView
heipei authored
44 [historySplitView setTopMin:33.0 andBottomMin:100.0];
45 [historySplitView uncollapse];
e329493 @pieter Move toolbar to view xib
pieter authored
46 [super awakeFromNib];
d6a0b1b @pieter Use a separate controller for tabs
pieter authored
47 }
48
49 - (void) updateKeys
50 {
6ba944b @pieter Implement a DetailsController
pieter authored
51 NSArray* selection = [commitController selectedObjects];
708c08a @pieter First part of splitting views
pieter authored
52
e2b5073 @pieter Delete temporary files when they are deallocated
pieter authored
53 // Remove any references in the QLPanel
708c08a @pieter First part of splitting views
pieter authored
54 //[[QLPreviewPanel sharedPreviewPanel] setURLs:[NSArray array] currentIndex:0 preservingDisplayState:YES];
e2b5073 @pieter Delete temporary files when they are deallocated
pieter authored
55 // We have to do this manually, as NSTreeController leaks memory?
708c08a @pieter First part of splitting views
pieter authored
56 //[treeController setSelectionIndexPaths:[NSArray array]];
57
6ba944b @pieter Implement a DetailsController
pieter authored
58 if ([selection count] > 0)
59 realCommit = [selection objectAtIndex:0];
60 else
61 realCommit = nil;
62
d6a0b1b @pieter Use a separate controller for tabs
pieter authored
63 self.webCommit = nil;
64 self.rawCommit = nil;
65 self.gitTree = nil;
708c08a @pieter First part of splitting views
pieter authored
66
2b0a4da @ciaran There’s no need for selectedTab to be an NSNumber (and certainly not an ...
ciaran authored
67 switch (self.selectedTab) {
68 case 0: self.webCommit = realCommit; break;
34394d0 @pieter HistoryView: Remove raw view
pieter authored
69 case 1: self.gitTree = realCommit.tree; break;
2b0a4da @ciaran There’s no need for selectedTab to be an NSNumber (and certainly not an ...
ciaran authored
70 }
d6a0b1b @pieter Use a separate controller for tabs
pieter authored
71 }
72
73
2b0a4da @ciaran There’s no need for selectedTab to be an NSNumber (and certainly not an ...
ciaran authored
74 - (void) setSelectedTab: (int) number
d6a0b1b @pieter Use a separate controller for tabs
pieter authored
75 {
76 selectedTab = number;
8de6a10 @ciaran Remember the currently selected tab across sessions.
ciaran authored
77 [[NSUserDefaults standardUserDefaults] setInteger:selectedTab forKey:@"Repository Window Selected Tab Index"];
d6a0b1b @pieter Use a separate controller for tabs
pieter authored
78 [self updateKeys];
79 }
6ba944b @pieter Implement a DetailsController
pieter authored
80
81 - (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
82 {
83 if ([(NSString *)context isEqualToString: @"commitChange"]) {
84 [self updateKeys];
85 return;
86 }
28e8bac @pieter Add QuickLook support in tree view
pieter authored
87 else if ([(NSString *)context isEqualToString: @"treeChange"]) {
708c08a @pieter First part of splitting views
pieter authored
88 [self updateQuicklookForce: NO];
28e8bac @pieter Add QuickLook support in tree view
pieter authored
89 }
0d0a83f @pieter HistoryView: Reset the sorting after selecting another branch
pieter authored
90 else if([(NSString *)context isEqualToString:@"branchChange"]) {
91 // Reset the sorting
92 commitController.sortDescriptors = [NSArray array];
93 }
6ba944b @pieter Implement a DetailsController
pieter authored
94 else {
95 [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
96 }
97 }
98
cc6ac22 @pieter Allow double click to open file
pieter authored
99 - (IBAction) openSelectedFile: sender
100 {
101 NSArray* selectedFiles = [treeController selectedObjects];
102 if ([selectedFiles count] == 0)
103 return;
104 PBGitTree* tree = [selectedFiles objectAtIndex:0];
105 NSString* name = [tree tmpFileNameForContents];
106 [[NSWorkspace sharedWorkspace] openTempFile:name];
107 }
108
e6da252 @pieter Add shortcuts and menu items for different views
pieter authored
109 - (IBAction) setDetailedView: sender {
2b0a4da @ciaran There’s no need for selectedTab to be an NSNumber (and certainly not an ...
ciaran authored
110 self.selectedTab = 0;
e6da252 @pieter Add shortcuts and menu items for different views
pieter authored
111 }
112 - (IBAction) setRawView: sender {
2b0a4da @ciaran There’s no need for selectedTab to be an NSNumber (and certainly not an ...
ciaran authored
113 self.selectedTab = 1;
e6da252 @pieter Add shortcuts and menu items for different views
pieter authored
114 }
115 - (IBAction) setTreeView: sender {
2b0a4da @ciaran There’s no need for selectedTab to be an NSNumber (and certainly not an ...
ciaran authored
116 self.selectedTab = 2;
e6da252 @pieter Add shortcuts and menu items for different views
pieter authored
117 }
118
159924a @ciaran Add the standard ⌥⌘F shortcut to focus the search field in the toolbar
ciaran authored
119 - (void)keyDown:(NSEvent*)event
120 {
121 if ([[event charactersIgnoringModifiers] isEqualToString: @"f"] && [event modifierFlags] & NSAlternateKeyMask && [event modifierFlags] & NSCommandKeyMask)
e329493 @pieter Move toolbar to view xib
pieter authored
122 [superController.window makeFirstResponder: searchField];
159924a @ciaran Add the standard ⌥⌘F shortcut to focus the search field in the toolbar
ciaran authored
123 else
124 [super keyDown: event];
125 }
126
de9f4dd @pieter HistoryView: Add copy behaviour in commit list
pieter authored
127 - (void) copyCommitInfo
128 {
129 PBGitCommit *commit = [[commitController selectedObjects] objectAtIndex:0];
130 if (!commit)
131 return;
ea0b28d @pieter Fix copying of commits
pieter authored
132 NSString *info = [NSString stringWithFormat:@"%@ (%@)", [[commit realSha] substringToIndex:10], [commit subject]];
de9f4dd @pieter HistoryView: Add copy behaviour in commit list
pieter authored
133
134 NSPasteboard *a =[NSPasteboard generalPasteboard];
135 [a declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:self];
136 [a setString:info forType: NSStringPboardType];
137
138 }
139
28e8bac @pieter Add QuickLook support in tree view
pieter authored
140 - (IBAction) toggleQuickView: sender
141 {
142 id panel = [QLPreviewPanel sharedPreviewPanel];
143 if ([panel isOpen]) {
144 [panel closePanel];
145 } else {
146 [[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFrontWithEffect:1];
b18b957 @pieter Allow QuickLook to activate by pressing space
pieter authored
147 [self updateQuicklookForce: YES];
28e8bac @pieter Add QuickLook support in tree view
pieter authored
148 }
149 }
150
b18b957 @pieter Allow QuickLook to activate by pressing space
pieter authored
151 - (void) updateQuicklookForce: (BOOL) force
28e8bac @pieter Add QuickLook support in tree view
pieter authored
152 {
b18b957 @pieter Allow QuickLook to activate by pressing space
pieter authored
153 if (!force && ![[QLPreviewPanel sharedPreviewPanel] isOpen])
28e8bac @pieter Add QuickLook support in tree view
pieter authored
154 return;
155
156 NSArray* selectedFiles = [treeController selectedObjects];
708c08a @pieter First part of splitting views
pieter authored
157
28e8bac @pieter Add QuickLook support in tree view
pieter authored
158 if ([selectedFiles count] == 0)
159 return;
160
161 NSMutableArray* fileNames = [NSMutableArray array];
162 for (PBGitTree* tree in selectedFiles) {
163 NSString* s = [tree tmpFileNameForContents];
164 if (s)
165 [fileNames addObject:[NSURL fileURLWithPath: s]];
166 }
708c08a @pieter First part of splitting views
pieter authored
167
28e8bac @pieter Add QuickLook support in tree view
pieter authored
168 [[QLPreviewPanel sharedPreviewPanel] setURLs:fileNames currentIndex:0 preservingDisplayState:YES];
708c08a @pieter First part of splitting views
pieter authored
169
28e8bac @pieter Add QuickLook support in tree view
pieter authored
170 }
e6da252 @pieter Add shortcuts and menu items for different views
pieter authored
171
3c481e4 @pieter Add a Refresh menu item
pieter authored
172 - (IBAction) refresh: sender
173 {
1f783c9 @pieter Reload refs on refresh
pieter authored
174 [repository reloadRefs];
175 [repository.revisionList reload];
3c481e4 @pieter Add a Refresh menu item
pieter authored
176 }
177
cd4ee1b @pieter Update views when switching
pieter authored
178 - (void) updateView
179 {
180 [self refresh:nil];
181 }
182
f2a37df @nriley Set keyboard focus reasonably when switching between views.
nriley authored
183 - (NSResponder *)firstResponder;
184 {
185 return commitList;
186 }
187
8c076bb @pieter Fix the 'parent' link in commits
pieter authored
188 - (void) selectCommit: (NSString*) commit
189 {
4591557 @pieter WebHistoryView: Fix displaying of parents
pieter authored
190 NSPredicate* selection = [NSPredicate predicateWithFormat:@"realSha == %@", commit];
8c076bb @pieter Fix the 'parent' link in commits
pieter authored
191 NSArray* selectedCommits = [repository.revisionList.commits filteredArrayUsingPredicate:selection];
192 [commitController setSelectedObjects: selectedCommits];
193 int index = [[commitController selectionIndexes] firstIndex];
194 [commitList scrollRowToVisible: index];
195 }
708c08a @pieter First part of splitting views
pieter authored
196
8c01a29 @pieter HistoryView: Don't show path lines if the list is changed
pieter authored
197 - (BOOL) hasNonlinearPath
198 {
199 return [commitController filterPredicate] || [[commitController sortDescriptors] count] > 0;
200 }
1028157 @pieter Fix memory leaks
pieter authored
201
202 - (void) removeView
203 {
204 [webView close];
3dd6385 @pieter Fix memory leaks
pieter authored
205 [commitController removeObserver:self forKeyPath:@"selection"];
206 [treeController removeObserver:self forKeyPath:@"selection"];
207 [repository removeObserver:self forKeyPath:@"currentBranch"];
208
1028157 @pieter Fix memory leaks
pieter authored
209 [super removeView];
210 }
23c9186 @pieter HistoryView: Allow creation of branches
pieter authored
211
47e182a @pieter HistoryController: Add some marks
pieter authored
212 #pragma mark Table Column Methods
8273aec Allow a user to select which columns to display
Pieter de Bie authored
213 - (NSMenu *)tableColumnMenu
214 {
215 NSMenu *menu = [[NSMenu alloc] initWithTitle:@"Table columns menu"];
216 for (NSTableColumn *column in [commitList tableColumns]) {
217 NSMenuItem *item = [[NSMenuItem alloc] init];
218 [item setTitle:[[column headerCell] stringValue]];
219 [item bind:@"value"
220 toObject:column
221 withKeyPath:@"hidden"
222 options:[NSDictionary dictionaryWithObject:@"NSNegateBoolean" forKey:NSValueTransformerNameBindingOption]];
223 [menu addItem:item];
224 }
225 return menu;
226 }
227
47e182a @pieter HistoryController: Add some marks
pieter authored
228 #pragma mark Tree Context Menu Methods
229
dc234cf @heipei PBGitHistory: Add "Show in Finder" to files
heipei authored
230 - (void)showCommitsFromTree:(id)sender
d973dc5 Display context menu in the history tree to show related commits
Pieter de Bie authored
231 {
232 // TODO: Enable this from webview as well!
233
234 NSMutableArray *filePaths = [NSMutableArray arrayWithObjects:@"HEAD", @"--", NULL];
1199c56 @pieter HistoryController: Use a programatically created context menu
pieter authored
235 [filePaths addObjectsFromArray:[sender representedObject]];
236
d973dc5 Display context menu in the history tree to show related commits
Pieter de Bie authored
237 PBGitRevSpecifier *revSpec = [[PBGitRevSpecifier alloc] initWithParameters:filePaths];
238
239 repository.currentBranch = [repository addBranch:revSpec];
240 }
241
dc234cf @heipei PBGitHistory: Add "Show in Finder" to files
heipei authored
242 - (void)showInFinderAction:(id)sender
243 {
244 NSString *workingDirectory = [[repository workingDirectory] stringByAppendingString:@"/"];
245 NSString *path;
246 NSWorkspace *ws = [NSWorkspace sharedWorkspace];
247
1199c56 @pieter HistoryController: Use a programatically created context menu
pieter authored
248 for (NSString *filePath in [sender representedObject]) {
249 path = [workingDirectory stringByAppendingPathComponent:filePath];
dc234cf @heipei PBGitHistory: Add "Show in Finder" to files
heipei authored
250 [ws selectFile: path inFileViewerRootedAtPath:path];
251 }
252
253 }
254
7427cbe @pieter HistoryController: Add "Open Files" menu item
pieter authored
255 - (void)openFilesAction:(id)sender
256 {
257 NSString *workingDirectory = [[repository workingDirectory] stringByAppendingString:@"/"];
258 NSString *path;
259 NSWorkspace *ws = [NSWorkspace sharedWorkspace];
260
261 for (NSString *filePath in [sender representedObject]) {
262 path = [workingDirectory stringByAppendingPathComponent:filePath];
263 [ws openFile:path];
264 }
265 }
266
267
1199c56 @pieter HistoryController: Use a programatically created context menu
pieter authored
268 - (NSMenu *)contextMenuForTreeView
269 {
270 NSArray *filePaths = [[treeController selectedObjects] valueForKey:@"fullPath"];
271
272 NSMenu *menu = [[NSMenu alloc] init];
273 for (NSMenuItem *item in [self menuItemsForPaths:filePaths])
274 [menu addItem:item];
275 return menu;
276 }
277
278 - (NSArray *)menuItemsForPaths:(NSArray *)paths
279 {
280 BOOL multiple = [paths count] != 1;
281 NSMenuItem *historyItem = [[NSMenuItem alloc] initWithTitle:multiple? @"Show history of files" : @"Show history of file"
282 action:@selector(showCommitsFromTree:)
283 keyEquivalent:@""];
7427cbe @pieter HistoryController: Add "Open Files" menu item
pieter authored
284 NSMenuItem *finderItem = [[NSMenuItem alloc] initWithTitle:@"Show in Finder"
285 action:@selector(showInFinderAction:)
286 keyEquivalent:@""];
287 NSMenuItem *openFilesItem = [[NSMenuItem alloc] initWithTitle:multiple? @"Open Files" : @"Open File"
288 action:@selector(openFilesAction:)
289 keyEquivalent:@""];
1199c56 @pieter HistoryController: Use a programatically created context menu
pieter authored
290
7427cbe @pieter HistoryController: Add "Open Files" menu item
pieter authored
291 NSArray *menuItems = [NSArray arrayWithObjects:historyItem, finderItem, openFilesItem, nil];
1199c56 @pieter HistoryController: Use a programatically created context menu
pieter authored
292 for (NSMenuItem *item in menuItems) {
293 [item setTarget:self];
294 [item setRepresentedObject:paths];
295 }
296
297 return menuItems;
298 }
dc234cf @heipei PBGitHistory: Add "Show in Finder" to files
heipei authored
299
d669050 @heipei Add PBCollapsibleSplitView as subclass of PBNiceSplitView
heipei authored
300 - (BOOL)splitView:(NSSplitView *)sender canCollapseSubview:(NSView *)subview {
301 return TRUE;
302 }
303
304 - (BOOL)splitView:(NSSplitView *)splitView shouldCollapseSubview:(NSView *)subview forDoubleClickOnDividerAtIndex:(NSInteger)dividerIndex {
305 int index = [[splitView subviews] indexOfObject:subview];
306 // this method (and canCollapse) are called by the splitView to decide how to collapse on double-click
307 // we compare our two subviews, so that always the smaller one is collapsed.
308 if([[[splitView subviews] objectAtIndex:index] frame].size.height < [[[splitView subviews] objectAtIndex:((index+1)%2)] frame].size.height) {
309 return TRUE;
310 }
311 return FALSE;
312 }
313
314 - (CGFloat)splitView:(NSSplitView *)sender constrainMinCoordinate:(CGFloat)proposedMin ofSubviewAt:(NSInteger)offset {
315 return proposedMin + historySplitView.topViewMin;
316 }
317
318 - (CGFloat)splitView:(NSSplitView *)sender constrainMaxCoordinate:(CGFloat)proposedMax ofSubviewAt:(NSInteger)offset {
86f9adb @d0k Fix an obvious typo
d0k authored
319 if(offset == 1)
d669050 @heipei Add PBCollapsibleSplitView as subclass of PBNiceSplitView
heipei authored
320 return proposedMax - historySplitView.bottomViewMin;
321 return [sender frame].size.height;
322 }
323
d6a0b1b @pieter Use a separate controller for tabs
pieter authored
324 @end
Something went wrong with that request. Please try again.