mirror of
https://github.com/kennethreitz-archive/gitx.git
synced 2026-06-05 23:40:18 +00:00
34394d056b
I don't think anybody has ever used this, so let's just remove it.
325 lines
9.9 KiB
Objective-C
325 lines
9.9 KiB
Objective-C
//
|
|
// PBGitHistoryView.m
|
|
// GitX
|
|
//
|
|
// Created by Pieter de Bie on 19-09-08.
|
|
// Copyright 2008 __MyCompanyName__. All rights reserved.
|
|
//
|
|
|
|
#import "PBGitHistoryController.h"
|
|
#import "CWQuickLook.h"
|
|
#import "PBGitGrapher.h"
|
|
#import "PBGitRevisionCell.h"
|
|
#import "PBCommitList.h"
|
|
#define QLPreviewPanel NSClassFromString(@"QLPreviewPanel")
|
|
|
|
|
|
@implementation PBGitHistoryController
|
|
@synthesize selectedTab, webCommit, rawCommit, gitTree, commitController;
|
|
|
|
- (void)awakeFromNib
|
|
{
|
|
self.selectedTab = [[NSUserDefaults standardUserDefaults] integerForKey:@"Repository Window Selected Tab Index"];;
|
|
[commitController addObserver:self forKeyPath:@"selection" options:(NSKeyValueObservingOptionNew,NSKeyValueObservingOptionOld) context:@"commitChange"];
|
|
[treeController addObserver:self forKeyPath:@"selection" options:0 context:@"treeChange"];
|
|
[repository addObserver:self forKeyPath:@"currentBranch" options:0 context:@"branchChange"];
|
|
NSSize cellSpacing = [commitList intercellSpacing];
|
|
cellSpacing.height = 0;
|
|
[commitList setIntercellSpacing:cellSpacing];
|
|
[fileBrowser setTarget:self];
|
|
[fileBrowser setDoubleAction:@selector(openSelectedFile:)];
|
|
|
|
if (!repository.currentBranch) {
|
|
[repository reloadRefs];
|
|
[repository readCurrentBranch];
|
|
}
|
|
else
|
|
[repository lazyReload];
|
|
|
|
// Set a sort descriptor for the subject column in the history list, as
|
|
// It can't be sorted by default (because it's bound to a PBGitCommit)
|
|
[[commitList tableColumnWithIdentifier:@"subject"] setSortDescriptorPrototype:[[NSSortDescriptor alloc] initWithKey:@"subject" ascending:YES]];
|
|
// Add a menu that allows a user to select which columns to view
|
|
[[commitList headerView] setMenu:[self tableColumnMenu]];
|
|
[historySplitView setTopMin:33.0 andBottomMin:100.0];
|
|
[historySplitView uncollapse];
|
|
[super awakeFromNib];
|
|
}
|
|
|
|
- (void) updateKeys
|
|
{
|
|
NSArray* selection = [commitController selectedObjects];
|
|
|
|
// Remove any references in the QLPanel
|
|
//[[QLPreviewPanel sharedPreviewPanel] setURLs:[NSArray array] currentIndex:0 preservingDisplayState:YES];
|
|
// We have to do this manually, as NSTreeController leaks memory?
|
|
//[treeController setSelectionIndexPaths:[NSArray array]];
|
|
|
|
if ([selection count] > 0)
|
|
realCommit = [selection objectAtIndex:0];
|
|
else
|
|
realCommit = nil;
|
|
|
|
self.webCommit = nil;
|
|
self.rawCommit = nil;
|
|
self.gitTree = nil;
|
|
|
|
switch (self.selectedTab) {
|
|
case 0: self.webCommit = realCommit; break;
|
|
case 1: self.gitTree = realCommit.tree; break;
|
|
}
|
|
}
|
|
|
|
|
|
- (void) setSelectedTab: (int) number
|
|
{
|
|
selectedTab = number;
|
|
[[NSUserDefaults standardUserDefaults] setInteger:selectedTab forKey:@"Repository Window Selected Tab Index"];
|
|
[self updateKeys];
|
|
}
|
|
|
|
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
|
{
|
|
if ([(NSString *)context isEqualToString: @"commitChange"]) {
|
|
[self updateKeys];
|
|
return;
|
|
}
|
|
else if ([(NSString *)context isEqualToString: @"treeChange"]) {
|
|
[self updateQuicklookForce: NO];
|
|
}
|
|
else if([(NSString *)context isEqualToString:@"branchChange"]) {
|
|
// Reset the sorting
|
|
commitController.sortDescriptors = [NSArray array];
|
|
}
|
|
else {
|
|
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
|
|
}
|
|
}
|
|
|
|
- (IBAction) openSelectedFile: sender
|
|
{
|
|
NSArray* selectedFiles = [treeController selectedObjects];
|
|
if ([selectedFiles count] == 0)
|
|
return;
|
|
PBGitTree* tree = [selectedFiles objectAtIndex:0];
|
|
NSString* name = [tree tmpFileNameForContents];
|
|
[[NSWorkspace sharedWorkspace] openTempFile:name];
|
|
}
|
|
|
|
- (IBAction) setDetailedView: sender {
|
|
self.selectedTab = 0;
|
|
}
|
|
- (IBAction) setRawView: sender {
|
|
self.selectedTab = 1;
|
|
}
|
|
- (IBAction) setTreeView: sender {
|
|
self.selectedTab = 2;
|
|
}
|
|
|
|
- (void)keyDown:(NSEvent*)event
|
|
{
|
|
if ([[event charactersIgnoringModifiers] isEqualToString: @"f"] && [event modifierFlags] & NSAlternateKeyMask && [event modifierFlags] & NSCommandKeyMask)
|
|
[superController.window makeFirstResponder: searchField];
|
|
else
|
|
[super keyDown: event];
|
|
}
|
|
|
|
- (void) copyCommitInfo
|
|
{
|
|
PBGitCommit *commit = [[commitController selectedObjects] objectAtIndex:0];
|
|
if (!commit)
|
|
return;
|
|
NSString *info = [NSString stringWithFormat:@"%@ (%@)", [[commit realSha] substringToIndex:10], [commit subject]];
|
|
|
|
NSPasteboard *a =[NSPasteboard generalPasteboard];
|
|
[a declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:self];
|
|
[a setString:info forType: NSStringPboardType];
|
|
|
|
}
|
|
|
|
- (IBAction) toggleQuickView: sender
|
|
{
|
|
id panel = [QLPreviewPanel sharedPreviewPanel];
|
|
if ([panel isOpen]) {
|
|
[panel closePanel];
|
|
} else {
|
|
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFrontWithEffect:1];
|
|
[self updateQuicklookForce: YES];
|
|
}
|
|
}
|
|
|
|
- (void) updateQuicklookForce: (BOOL) force
|
|
{
|
|
if (!force && ![[QLPreviewPanel sharedPreviewPanel] isOpen])
|
|
return;
|
|
|
|
NSArray* selectedFiles = [treeController selectedObjects];
|
|
|
|
if ([selectedFiles count] == 0)
|
|
return;
|
|
|
|
NSMutableArray* fileNames = [NSMutableArray array];
|
|
for (PBGitTree* tree in selectedFiles) {
|
|
NSString* s = [tree tmpFileNameForContents];
|
|
if (s)
|
|
[fileNames addObject:[NSURL fileURLWithPath: s]];
|
|
}
|
|
|
|
[[QLPreviewPanel sharedPreviewPanel] setURLs:fileNames currentIndex:0 preservingDisplayState:YES];
|
|
|
|
}
|
|
|
|
- (IBAction) refresh: sender
|
|
{
|
|
[repository reloadRefs];
|
|
[repository.revisionList reload];
|
|
}
|
|
|
|
- (void) updateView
|
|
{
|
|
[self refresh:nil];
|
|
}
|
|
|
|
- (NSResponder *)firstResponder;
|
|
{
|
|
return commitList;
|
|
}
|
|
|
|
- (void) selectCommit: (NSString*) commit
|
|
{
|
|
NSPredicate* selection = [NSPredicate predicateWithFormat:@"realSha == %@", commit];
|
|
NSArray* selectedCommits = [repository.revisionList.commits filteredArrayUsingPredicate:selection];
|
|
[commitController setSelectedObjects: selectedCommits];
|
|
int index = [[commitController selectionIndexes] firstIndex];
|
|
[commitList scrollRowToVisible: index];
|
|
}
|
|
|
|
- (BOOL) hasNonlinearPath
|
|
{
|
|
return [commitController filterPredicate] || [[commitController sortDescriptors] count] > 0;
|
|
}
|
|
|
|
- (void) removeView
|
|
{
|
|
[webView close];
|
|
[commitController removeObserver:self forKeyPath:@"selection"];
|
|
[treeController removeObserver:self forKeyPath:@"selection"];
|
|
[repository removeObserver:self forKeyPath:@"currentBranch"];
|
|
|
|
[super removeView];
|
|
}
|
|
|
|
#pragma mark Table Column Methods
|
|
- (NSMenu *)tableColumnMenu
|
|
{
|
|
NSMenu *menu = [[NSMenu alloc] initWithTitle:@"Table columns menu"];
|
|
for (NSTableColumn *column in [commitList tableColumns]) {
|
|
NSMenuItem *item = [[NSMenuItem alloc] init];
|
|
[item setTitle:[[column headerCell] stringValue]];
|
|
[item bind:@"value"
|
|
toObject:column
|
|
withKeyPath:@"hidden"
|
|
options:[NSDictionary dictionaryWithObject:@"NSNegateBoolean" forKey:NSValueTransformerNameBindingOption]];
|
|
[menu addItem:item];
|
|
}
|
|
return menu;
|
|
}
|
|
|
|
#pragma mark Tree Context Menu Methods
|
|
|
|
- (void)showCommitsFromTree:(id)sender
|
|
{
|
|
// TODO: Enable this from webview as well!
|
|
|
|
NSMutableArray *filePaths = [NSMutableArray arrayWithObjects:@"HEAD", @"--", NULL];
|
|
[filePaths addObjectsFromArray:[sender representedObject]];
|
|
|
|
PBGitRevSpecifier *revSpec = [[PBGitRevSpecifier alloc] initWithParameters:filePaths];
|
|
|
|
repository.currentBranch = [repository addBranch:revSpec];
|
|
}
|
|
|
|
- (void)showInFinderAction:(id)sender
|
|
{
|
|
NSString *workingDirectory = [[repository workingDirectory] stringByAppendingString:@"/"];
|
|
NSString *path;
|
|
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
|
|
|
|
for (NSString *filePath in [sender representedObject]) {
|
|
path = [workingDirectory stringByAppendingPathComponent:filePath];
|
|
[ws selectFile: path inFileViewerRootedAtPath:path];
|
|
}
|
|
|
|
}
|
|
|
|
- (void)openFilesAction:(id)sender
|
|
{
|
|
NSString *workingDirectory = [[repository workingDirectory] stringByAppendingString:@"/"];
|
|
NSString *path;
|
|
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
|
|
|
|
for (NSString *filePath in [sender representedObject]) {
|
|
path = [workingDirectory stringByAppendingPathComponent:filePath];
|
|
[ws openFile:path];
|
|
}
|
|
}
|
|
|
|
|
|
- (NSMenu *)contextMenuForTreeView
|
|
{
|
|
NSArray *filePaths = [[treeController selectedObjects] valueForKey:@"fullPath"];
|
|
|
|
NSMenu *menu = [[NSMenu alloc] init];
|
|
for (NSMenuItem *item in [self menuItemsForPaths:filePaths])
|
|
[menu addItem:item];
|
|
return menu;
|
|
}
|
|
|
|
- (NSArray *)menuItemsForPaths:(NSArray *)paths
|
|
{
|
|
BOOL multiple = [paths count] != 1;
|
|
NSMenuItem *historyItem = [[NSMenuItem alloc] initWithTitle:multiple? @"Show history of files" : @"Show history of file"
|
|
action:@selector(showCommitsFromTree:)
|
|
keyEquivalent:@""];
|
|
NSMenuItem *finderItem = [[NSMenuItem alloc] initWithTitle:@"Show in Finder"
|
|
action:@selector(showInFinderAction:)
|
|
keyEquivalent:@""];
|
|
NSMenuItem *openFilesItem = [[NSMenuItem alloc] initWithTitle:multiple? @"Open Files" : @"Open File"
|
|
action:@selector(openFilesAction:)
|
|
keyEquivalent:@""];
|
|
|
|
NSArray *menuItems = [NSArray arrayWithObjects:historyItem, finderItem, openFilesItem, nil];
|
|
for (NSMenuItem *item in menuItems) {
|
|
[item setTarget:self];
|
|
[item setRepresentedObject:paths];
|
|
}
|
|
|
|
return menuItems;
|
|
}
|
|
|
|
- (BOOL)splitView:(NSSplitView *)sender canCollapseSubview:(NSView *)subview {
|
|
return TRUE;
|
|
}
|
|
|
|
- (BOOL)splitView:(NSSplitView *)splitView shouldCollapseSubview:(NSView *)subview forDoubleClickOnDividerAtIndex:(NSInteger)dividerIndex {
|
|
int index = [[splitView subviews] indexOfObject:subview];
|
|
// this method (and canCollapse) are called by the splitView to decide how to collapse on double-click
|
|
// we compare our two subviews, so that always the smaller one is collapsed.
|
|
if([[[splitView subviews] objectAtIndex:index] frame].size.height < [[[splitView subviews] objectAtIndex:((index+1)%2)] frame].size.height) {
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
- (CGFloat)splitView:(NSSplitView *)sender constrainMinCoordinate:(CGFloat)proposedMin ofSubviewAt:(NSInteger)offset {
|
|
return proposedMin + historySplitView.topViewMin;
|
|
}
|
|
|
|
- (CGFloat)splitView:(NSSplitView *)sender constrainMaxCoordinate:(CGFloat)proposedMax ofSubviewAt:(NSInteger)offset {
|
|
if(offset == 1)
|
|
return proposedMax - historySplitView.bottomViewMin;
|
|
return [sender frame].size.height;
|
|
}
|
|
|
|
@end
|