diff --git a/.gitignore b/.gitignore index 94061ea..6492eef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ build build/revision +._* *.xcodeproj/ !*.xcodeproj/project.pbxproj Nightly.app.zip diff --git a/Commands/PBCommand.h b/Commands/PBCommand.h new file mode 100644 index 0000000..8e3c1ae --- /dev/null +++ b/Commands/PBCommand.h @@ -0,0 +1,36 @@ +// +// PBCommand.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBGitRepository.h" + +@interface PBCommand : NSObject { + PBGitRepository *repository; + + // for the user to see what it triggers + NSString *displayName; + // shown during command execution + NSString *commandTitle; + NSString *commandDescription; + + NSMutableArray *parameters; + BOOL canBeFired; +} +@property (nonatomic) BOOL canBeFired; +@property (nonatomic, retain, readonly) PBGitRepository *repository; +@property (nonatomic, retain) NSString *commandTitle; +@property (nonatomic, retain) NSString *commandDescription; +@property (nonatomic, copy) NSString *displayName; + +- (id) initWithDisplayName:(NSString *) aDisplayName parameters:(NSArray *) params repository:(PBGitRepository *) repo; + +- (void) invoke; + +- (NSArray *) allParameters; +- (void) appendParameters:(NSArray *) params; +@end diff --git a/Commands/PBCommand.m b/Commands/PBCommand.m new file mode 100644 index 0000000..a36364c --- /dev/null +++ b/Commands/PBCommand.m @@ -0,0 +1,64 @@ +// +// PBCommand.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBCommand.h" +#import "PBRemoteProgressSheet.h" + +@interface PBCommand() +@property (nonatomic, retain) PBGitRepository *repository; +@end + +@implementation PBCommand +@synthesize displayName; +@synthesize commandDescription; +@synthesize commandTitle; +@synthesize repository; +@synthesize canBeFired; + +- (id) initWithDisplayName:(NSString *) aDisplayName parameters:(NSArray *) params { + return [self initWithDisplayName:aDisplayName parameters:params repository:nil]; +} + +- (id) initWithDisplayName:(NSString *) aDisplayName parameters:(NSArray *) params repository:(PBGitRepository *) repo { + self = [super init]; + if (self != nil) { + self.displayName = aDisplayName; + parameters = [[NSMutableArray alloc] initWithArray:params]; + + // default values + self.commandTitle = @""; + self.commandDescription = @""; + self.repository = repo; + self.canBeFired = YES; + } + return self; +} + + +- (void) dealloc { + [repository release]; + [commandDescription release]; + [commandTitle release]; + [parameters release]; + [displayName release]; + [super dealloc]; +} + +- (NSArray *) allParameters { + return parameters; +} + +- (void) appendParameters:(NSArray *) params { + [parameters addObjectsFromArray:params]; +} + +- (void) invoke { + [PBRemoteProgressSheet beginRemoteProgressSheetForArguments:[self allParameters] title:self.commandTitle description:self.commandDescription inRepository:self.repository]; +} + +@end diff --git a/Commands/PBCommandFactory.h b/Commands/PBCommandFactory.h new file mode 100644 index 0000000..a613c7b --- /dev/null +++ b/Commands/PBCommandFactory.h @@ -0,0 +1,13 @@ +// +// PBCommandFactory.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBGitRepository.h" + +@protocol PBCommandFactory ++ (NSArray *) commandsForObject:(NSObject *) object repository:(PBGitRepository *) repository; +@end diff --git a/Commands/PBCommandWithParameter.h b/Commands/PBCommandWithParameter.h new file mode 100644 index 0000000..dea7830 --- /dev/null +++ b/Commands/PBCommandWithParameter.h @@ -0,0 +1,23 @@ +// +// PBCommandWithParameter.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBCommand.h" + + +@interface PBCommandWithParameter : PBCommand { + PBCommand *command; + NSString *parameterName; + NSString *parameterDisplayName; +} +@property (nonatomic, retain, readonly) PBCommand *command; +@property (nonatomic, retain, readonly) NSString *parameterName; +@property (nonatomic, retain, readonly) NSString *parameterDisplayName; + +- initWithCommand:(PBCommand *) command parameterName:(NSString *) param parameterDisplayName:(NSString *) paramDisplayName; +@end diff --git a/Commands/PBCommandWithParameter.m b/Commands/PBCommandWithParameter.m new file mode 100644 index 0000000..9f50b51 --- /dev/null +++ b/Commands/PBCommandWithParameter.m @@ -0,0 +1,40 @@ +// +// PBCommandWithParameter.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBCommandWithParameter.h" +#import "PBArgumentPickerController.h" + + +@implementation PBCommandWithParameter +@synthesize command; +@synthesize parameterName; +@synthesize parameterDisplayName; + +- initWithCommand:(PBCommand *) aCommand parameterName:(NSString *) param parameterDisplayName:(NSString *) paramDisplayName { + if (self = [super initWithDisplayName:[aCommand displayName] parameters:nil repository:[aCommand repository]]) { + command = [aCommand retain]; + parameterName = [param retain]; + parameterDisplayName = [paramDisplayName retain]; + } + return self; +} + +- (void) dealloc { + [command release]; + [parameterName release]; + [parameterDisplayName release]; + [super dealloc]; +} + + +- (void) invoke { + PBArgumentPickerController *controller = [[PBArgumentPickerController alloc] initWithCommandWithParameter:self]; + [NSApp beginSheet:[controller window] modalForWindow:[command.repository.windowController window] modalDelegate:controller didEndSelector:nil contextInfo:NULL]; + [controller release]; +} +@end diff --git a/Commands/PBOpenDocumentCommand.h b/Commands/PBOpenDocumentCommand.h new file mode 100644 index 0000000..1f51487 --- /dev/null +++ b/Commands/PBOpenDocumentCommand.h @@ -0,0 +1,17 @@ +// +// PBOpenDocumentCommand.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-07. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBCommand.h" + +@interface PBOpenDocumentCommand : PBCommand { + NSURL *documentURL; +} + +- (id) initWithDocumentAbsolutePath:(NSString *) path; +@end diff --git a/Commands/PBOpenDocumentCommand.m b/Commands/PBOpenDocumentCommand.m new file mode 100644 index 0000000..16f6906 --- /dev/null +++ b/Commands/PBOpenDocumentCommand.m @@ -0,0 +1,26 @@ +// +// PBOpenDocumentCommand.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-07. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBOpenDocumentCommand.h" +#import "PBRepositoryDocumentController.h" +#import "PBGitRepository.h" + +@implementation PBOpenDocumentCommand + +- (id) initWithDocumentAbsolutePath:(NSString *) path { + if (self = [super initWithDisplayName:@"Open" parameters:nil repository:nil]) { + documentURL = [[NSURL alloc] initWithString:path]; + } + return self; +} + +- (void) invoke { + [[PBRepositoryDocumentController sharedDocumentController] documentForLocation:documentURL]; +} + +@end diff --git a/Commands/PBRemoteCommandFactory.h b/Commands/PBRemoteCommandFactory.h new file mode 100644 index 0000000..b249e73 --- /dev/null +++ b/Commands/PBRemoteCommandFactory.h @@ -0,0 +1,17 @@ +// +// PBRemoteCommandFactory.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-07. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBCommandFactory.h" + + +@interface PBRemoteCommandFactory : NSObject { + +} + +@end diff --git a/Commands/PBRemoteCommandFactory.m b/Commands/PBRemoteCommandFactory.m new file mode 100644 index 0000000..2b02524 --- /dev/null +++ b/Commands/PBRemoteCommandFactory.m @@ -0,0 +1,68 @@ +// +// PBRemoteCommandFactory.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-07. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBRemoteCommandFactory.h" +#import "PBOpenDocumentCommand.h" +#import "PBGitSubmodule.h" +#import "PBRevealWithFinderCommand.h" + + +@implementation PBRemoteCommandFactory + ++ (NSArray *) commandsForSubmodule:(PBGitSubmodule *) submodule inRepository:(PBGitRepository *) repository { + NSMutableArray *commands = [[NSMutableArray alloc] init]; + + NSString *repoPath = [repository workingDirectory]; + NSString *path = [repoPath stringByAppendingPathComponent:[submodule path]]; + NSString *submodulePath = [submodule path]; + + if ([submodule submoduleState] == PBGitSubmoduleStateNotInitialized) { + NSArray *params = [NSArray arrayWithObjects:@"submodule", @"init", submodulePath, nil]; + PBCommand *initCmd = [[PBCommand alloc] initWithDisplayName:@"Init" parameters:params repository:repository]; + initCmd.commandTitle = initCmd.displayName; + initCmd.commandDescription = [NSString stringWithFormat:@"Initializing submodule %@", submodulePath]; + [commands addObject:initCmd]; + } + + // update + NSArray *params = [NSArray arrayWithObjects:@"submodule", @"update", submodulePath, nil]; + PBCommand *updateCmd = [[PBCommand alloc] initWithDisplayName:@"Update" parameters:params repository:repository]; + updateCmd.commandTitle = updateCmd.displayName; + updateCmd.commandDescription = [NSString stringWithFormat:@"Updating submodule %@", submodulePath]; + [commands addObject:updateCmd]; + + if ([[submodule submodules] count] > 0) { + // update recursively + NSArray *recursiveUpdate = [NSArray arrayWithObjects:@"submodule", @"update", @"--recursive", submodulePath, nil]; + PBCommand *updateRecursively = [[PBCommand alloc] initWithDisplayName:@"Update recursively" parameters:recursiveUpdate repository:repository]; + updateRecursively.commandTitle = updateRecursively.displayName; + updateRecursively.commandDescription = [NSString stringWithFormat:@"Updating submodule %@ (recursively)", submodulePath]; + [commands addObject:updateRecursively]; + } + + if ([submodule submoduleState] != PBGitSubmoduleStateNotInitialized) { + // open + PBOpenDocumentCommand *command = [[PBOpenDocumentCommand alloc] initWithDocumentAbsolutePath:path]; + command.commandTitle = command.displayName; + command.commandDescription = @"Opening document"; + [commands addObject:command]; + + [commands addObject:[[PBRevealWithFinderCommand alloc] initWithDocumentAbsolutePath:path]]; + } + + return commands; +} + ++ (NSArray *) commandsForObject:(NSObject *) object repository:(PBGitRepository *) repository { + if ([object isKindOfClass:[PBGitSubmodule class]]) { + return [PBRemoteCommandFactory commandsForSubmodule:(id)object inRepository:repository]; + } + return nil; +} + +@end diff --git a/Commands/PBRevealWithFinderCommand.h b/Commands/PBRevealWithFinderCommand.h new file mode 100644 index 0000000..a97f6f1 --- /dev/null +++ b/Commands/PBRevealWithFinderCommand.h @@ -0,0 +1,17 @@ +// +// PBRevealWithFinder.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-27. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBOpenDocumentCommand.h" + +@interface PBRevealWithFinderCommand : PBOpenDocumentCommand { + +} + + +@end diff --git a/Commands/PBRevealWithFinderCommand.m b/Commands/PBRevealWithFinderCommand.m new file mode 100644 index 0000000..2f94a58 --- /dev/null +++ b/Commands/PBRevealWithFinderCommand.m @@ -0,0 +1,31 @@ +// +// PBRevealWithFinder.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-27. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBRevealWithFinderCommand.h" + + +@implementation PBRevealWithFinderCommand + +- (id) initWithDocumentAbsolutePath:(NSString *) path { + if (!path) { + [self autorelease]; + return nil; + } + + if (self = [super initWithDisplayName:@"Reveal in Finder" parameters:nil repository:nil]) { + documentURL = [[NSURL alloc] initWithString:path]; + } + return self; +} + +- (void) invoke { + NSWorkspace *ws = [NSWorkspace sharedWorkspace]; + [ws selectFile:[documentURL absoluteString] inFileViewerRootedAtPath:nil]; +} + +@end diff --git a/Commands/PBStashCommandFactory.h b/Commands/PBStashCommandFactory.h new file mode 100644 index 0000000..d4e0983 --- /dev/null +++ b/Commands/PBStashCommandFactory.h @@ -0,0 +1,17 @@ +// +// PBStashCommandFactory.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBCommandFactory.h" + + +@interface PBStashCommandFactory : NSObject { + +} + +@end diff --git a/Commands/PBStashCommandFactory.m b/Commands/PBStashCommandFactory.m new file mode 100644 index 0000000..195cd7b --- /dev/null +++ b/Commands/PBStashCommandFactory.m @@ -0,0 +1,88 @@ +// +// PBStashCommandFactory.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBStashCommandFactory.h" +#import "PBCommand.h" +#import "PBCommandWithParameter.h" + +// model +#import "PBGitStash.h" +#import "PBGitRef.h" + +@interface PBStashCommandFactory() ++ (NSArray *) commandsForStash:(PBGitStash *) stash repository:(PBGitRepository *) repository; ++ (NSArray *) commandsForRef:(PBGitRef *) ref repository:(PBGitRepository *) repository; +@end + + +@implementation PBStashCommandFactory + ++ (NSArray *) commandsForObject:(NSObject *) object repository:(PBGitRepository *) repository { + NSArray *cmds = nil; + if ([object isKindOfClass:[PBGitStash class]]) { + cmds = [PBStashCommandFactory commandsForStash:(id)object repository:repository]; + } else if ([object isKindOfClass:[PBGitRef class]]) { + cmds = [PBStashCommandFactory commandsForRef:(id)object repository:repository]; + } + + + return cmds; +} + ++ (NSArray *) commandsForRef:(PBGitRef *) ref repository:(PBGitRepository *) repository { + NSMutableArray *commands = [[NSMutableArray alloc] init]; + + PBGitRef *headRef = [[repository headRef] ref]; + BOOL isHead = [ref isEqualToRef:headRef]; + + if (isHead) { + NSArray *args = [NSArray arrayWithObject:@"stash"]; + PBCommand *command = [[PBCommand alloc] initWithDisplayName:@"Stash local changes..." parameters:args repository:repository]; + command.commandTitle = command.displayName; + command.commandDescription = @"Stashing local changes"; + + PBCommandWithParameter *cmd = [[PBCommandWithParameter alloc] initWithCommand:command parameterName:@"save" parameterDisplayName:@"Stash message (optional)"]; + [command release]; + [commands addObject:cmd]; + [cmd release]; + + command = [[PBCommand alloc] initWithDisplayName:@"Clear stashes" parameters:[NSArray arrayWithObjects:@"stash", @"clear", nil] repository:repository]; + command.commandTitle = command.displayName; + command.commandDescription = @"Clearing stashes"; + [commands addObject:command]; + [command release]; + } + + return [commands autorelease]; +} + ++ (NSArray *) commandsForStash:(PBGitStash *) stash repository:(PBGitRepository *) repository { + NSMutableArray *commands = [[NSMutableArray alloc] init]; + + NSArray *args = [NSArray arrayWithObjects:@"stash", @"apply", [stash name], nil]; + PBCommand *command = [[PBCommand alloc] initWithDisplayName:@"Apply" parameters:args repository:repository]; + command.commandTitle = command.displayName; + command.commandDescription = [NSString stringWithFormat:@"Applying stash: '%@'", stash]; + [commands addObject:command]; + + args = [NSArray arrayWithObjects:@"stash", @"pop", [stash name], nil]; + command = [[PBCommand alloc] initWithDisplayName:@"Pop" parameters:args repository:repository]; + command.commandTitle = command.displayName; + command.commandDescription = [NSString stringWithFormat:@"Poping stash: '%@'", stash]; + [commands addObject:command]; + + args = [NSArray arrayWithObjects:@"stash", @"drop", [stash name], nil]; + command = [[PBCommand alloc] initWithDisplayName:@"Drop" parameters:args repository:repository]; + command.commandTitle = command.displayName; + command.commandDescription = [NSString stringWithFormat:@"Dropping stash: '%@'", stash]; + [commands addObject:command]; + + return [commands autorelease]; +} + +@end diff --git a/Controller/PBArgumentPickerController.h b/Controller/PBArgumentPickerController.h new file mode 100644 index 0000000..3811baa --- /dev/null +++ b/Controller/PBArgumentPickerController.h @@ -0,0 +1,25 @@ +// +// PBArgumentPickerController.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBCommand.h" +#import "PBArgumentPicker.h" + +@class PBCommandWithParameter; + +@interface PBArgumentPickerController : NSWindowController { + IBOutlet PBArgumentPicker *view; + + PBCommandWithParameter *cmdWithParameter; +} + +- initWithCommandWithParameter:(PBCommandWithParameter *) command; + +- (IBAction) okClicked:sender; +- (IBAction) cancelClicked:sender; +@end diff --git a/Controller/PBArgumentPickerController.m b/Controller/PBArgumentPickerController.m new file mode 100644 index 0000000..51d542e --- /dev/null +++ b/Controller/PBArgumentPickerController.m @@ -0,0 +1,50 @@ +// +// PBArgumentPickerController.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBArgumentPickerController.h" +#import "PBCommandWithParameter.h" + + +@implementation PBArgumentPickerController + +- initWithCommandWithParameter:(PBCommandWithParameter *) aCommand { + if (self = [super initWithWindowNibName:@"PBArgumentPicker" owner:self]) { + cmdWithParameter = [aCommand retain]; + } + return self; +} + +- (void) dealloc { + [cmdWithParameter release]; + + [super dealloc]; +} + +- (void) awakeFromNib { + NSString *stringToDisplay = [NSString stringWithFormat:@"%@:", [cmdWithParameter parameterDisplayName]]; + [view.label setTitleWithMnemonic:stringToDisplay]; +} + +- (IBAction) okClicked:sender { + NSString *userText = [view.textField stringValue]; + if ([userText length] > 0) { + NSString *paramName = [cmdWithParameter parameterName]; + [cmdWithParameter.command appendParameters:[NSArray arrayWithObjects:paramName, userText, nil]]; + } + [self cancelClicked:sender]; + + [cmdWithParameter.command invoke]; +} + +- (IBAction) cancelClicked:sender { + [NSApp endSheet:[self window]]; + [[self window] orderOut:self]; +} + + +@end diff --git a/Controller/PBGitResetController.h b/Controller/PBGitResetController.h new file mode 100644 index 0000000..b7a8d30 --- /dev/null +++ b/Controller/PBGitResetController.h @@ -0,0 +1,24 @@ +// +// PBGitResetController.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-27. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + +@class PBGitRepository; + +@interface PBGitResetController : NSObject { + PBGitRepository *repository; +} +- (id) initWithRepository:(PBGitRepository *) repo; + +- (NSArray *) menuItems; + + +// actions +- (void) resetHardToHead; + +@end diff --git a/Controller/PBGitResetController.m b/Controller/PBGitResetController.m new file mode 100644 index 0000000..773a74d --- /dev/null +++ b/Controller/PBGitResetController.m @@ -0,0 +1,87 @@ +// +// PBGitResetController.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-27. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBGitResetController.h" +#import "PBGitRepository.h" +#import "PBCommand.h" + +static NSString * const kCommandKey = @"command"; + +@implementation PBGitResetController + +- (id) initWithRepository:(PBGitRepository *) repo { + if (self = [super init]){ + repository = [repo retain]; + } + return self; +} + +- (void) resetHardToHead { + NSAlert *alert = [NSAlert alertWithMessageText:@"Reseting working copy and index" + defaultButton:@"Cancel" + alternateButton:nil + otherButton:@"Reset" + informativeTextWithFormat:@"Are you sure you want to reset your working copy and index? All changes to them will be gone!"]; + + NSArray *arguments = [NSArray arrayWithObjects:@"reset", @"--hard", @"HEAD", nil]; + PBCommand *cmd = [[PBCommand alloc] initWithDisplayName:@"Reset hard to HEAD" parameters:arguments repository:repository]; + cmd.commandTitle = cmd.displayName; + cmd.commandDescription = @"Reseting head"; + + NSMutableDictionary *info = [NSMutableDictionary dictionaryWithObject:cmd forKey:kCommandKey]; + + [alert beginSheetModalForWindow:[repository.windowController window] + modalDelegate:self + didEndSelector:@selector(confirmResetSheetDidEnd:returnCode:contextInfo:) + contextInfo:info]; +} + +- (void) reset { + //TODO missing implementation +} + +- (NSArray *) menuItems { + NSMenuItem *resetHeadHardly = [[NSMenuItem alloc] initWithTitle:@"Reset hard to HEAD" action:@selector(resetHardToHead) keyEquivalent:@""]; + [resetHeadHardly setTarget:self]; + + NSMenuItem *reset = [[NSMenuItem alloc] initWithTitle:@"Reset..." action:@selector(reset) keyEquivalent:@""]; + [reset setTarget:self]; + + return [NSArray arrayWithObjects:resetHeadHardly, reset, nil]; +} + +- (BOOL) validateMenuItem:(NSMenuItem *)menuItem { + BOOL shouldBeEnabled = YES; + SEL action = [menuItem action]; + if (action == @selector(reset)) { + shouldBeEnabled = NO; + //TODO missing implementation + } + return shouldBeEnabled; +} + +- (void) dealloc { + [repository release]; + [super dealloc]; +} + +#pragma mark - +#pragma mark Confirm Window + +- (void) confirmResetSheetDidEnd:(NSAlert *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo +{ + [[sheet window] orderOut:nil]; + + if (returnCode != NSAlertDefaultReturn) { + PBCommand *cmd = [(NSDictionary *)contextInfo objectForKey:kCommandKey]; + [cmd invoke]; + } +} + + +@end diff --git a/Controller/PBSubmoduleController.h b/Controller/PBSubmoduleController.h new file mode 100644 index 0000000..65294eb --- /dev/null +++ b/Controller/PBSubmoduleController.h @@ -0,0 +1,37 @@ +// +// PBSubmoduleController.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-27. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBGitSubmodule.h" + +@class PBGitRepository; +@class PBCommand; + +@interface PBSubmoduleController : NSObject { + NSArray *submodules; +@private + PBGitRepository *repository; +} +@property (nonatomic, retain, readonly) NSArray *submodules; + +- (id) initWithRepository:(PBGitRepository *) repo; + +- (void) reload; + +- (NSArray *) menuItems; + + +// actions + +- (void) addNewSubmodule; +- (void) initializeAllSubmodules; +- (void) updateAllSubmodules; + +- (PBCommand *) commandForOpeningSubmodule:(PBGitSubmodule *) submodule; +- (PBCommand *) defaultCommandForSubmodule:(PBGitSubmodule *) submodule; +@end diff --git a/Controller/PBSubmoduleController.m b/Controller/PBSubmoduleController.m new file mode 100644 index 0000000..7da580b --- /dev/null +++ b/Controller/PBSubmoduleController.m @@ -0,0 +1,133 @@ +// +// PBSubmoduleController.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-27. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBSubmoduleController.h" +#import "PBGitRepository.h" +#import "PBOpenDocumentCommand.h" + +@interface PBSubmoduleController() +@property (nonatomic, retain) NSArray *submodules; +@end + + +@implementation PBSubmoduleController +@synthesize submodules; + +- (id) initWithRepository:(PBGitRepository *) repo { + if (self = [super init]){ + repository = [repo retain]; + } + return self; +} + +- (void)dealloc { + [repository release]; + [submodules release]; + [super dealloc]; +} + +- (void) reload { + NSArray *arguments = [NSArray arrayWithObjects:@"submodule", @"status", @"--recursive", nil]; + NSString *output = [repository outputInWorkdirForArguments:arguments]; + NSArray *lines = [output componentsSeparatedByString:@"\n"]; + + NSMutableArray *loadedSubmodules = [[NSMutableArray alloc] initWithCapacity:[lines count]]; + + for (NSString *submoduleLine in lines) { + if ([submoduleLine length] == 0) + continue; + PBGitSubmodule *submodule = [[PBGitSubmodule alloc] initWithRawSubmoduleStatusString:submoduleLine]; + [loadedSubmodules addObject:submodule]; + } + + NSMutableArray *groupedSubmodules = [[NSMutableArray alloc] init]; + for (PBGitSubmodule *submodule in loadedSubmodules) { + BOOL added = NO; + for (PBGitSubmodule *addedItem in groupedSubmodules) { + if ([[submodule path] hasPrefix:[addedItem path]]) { + [addedItem addSubmodule:submodule]; + added = YES; + } + } + if (!added) { + [groupedSubmodules addObject:submodule]; + } + } + + + self.submodules = loadedSubmodules; +} + +#pragma mark - +#pragma mark Actions + +- (void) addNewSubmodule { + //TODO implement +} + +- (void) initializeAllSubmodules { + NSArray *parameters = [NSArray arrayWithObjects:@"submodule", @"init", nil]; + PBCommand *initializeSubmodules = [[PBCommand alloc] initWithDisplayName:@"Initialize All Submodules" parameters:parameters repository:repository]; + initializeSubmodules.commandTitle = initializeSubmodules.displayName; + initializeSubmodules.commandDescription = @"Initializing submodules"; + [initializeSubmodules invoke]; + [initializeSubmodules release]; +} + +- (void) updateAllSubmodules { + NSArray *parameters = [NSArray arrayWithObjects:@"submodule", @"update", nil]; + PBCommand *initializeSubmodules = [[PBCommand alloc] initWithDisplayName:@"Update All Submodules" parameters:parameters repository:repository]; + initializeSubmodules.commandTitle = initializeSubmodules.displayName; + initializeSubmodules.commandDescription = @"Updating submodules"; + [initializeSubmodules invoke]; + [initializeSubmodules release]; +} + +- (NSArray *) menuItems { + NSMutableArray *items = [[NSMutableArray alloc] init]; + [items addObject:[[NSMenuItem alloc] initWithTitle:@"Add Submodule..." action:@selector(addNewSubmodule) keyEquivalent:@""]]; + [items addObject:[[NSMenuItem alloc] initWithTitle:@"Initialize All Submodules" action:@selector(initializeAllSubmodules) keyEquivalent:@""]]; + [items addObject:[[NSMenuItem alloc] initWithTitle:@"Update All Submodules" action:@selector(updateAllSubmodules) keyEquivalent:@""]]; + + for (NSMenuItem *item in items) { + [item setTarget:self]; + } + + return items; +} + +- (PBCommand *) defaultCommandForSubmodule:(PBGitSubmodule *) submodule { + return [self commandForOpeningSubmodule:submodule]; +} + +- (PBCommand *) commandForOpeningSubmodule:(PBGitSubmodule *) submodule { + if (!([submodule path] && [submodule submoduleState] != PBGitSubmoduleStateNotInitialized)) { + return nil; + } + NSString *repoPath = [repository workingDirectory]; + NSString *path = [repoPath stringByAppendingPathComponent:[submodule path]]; + + PBOpenDocumentCommand *command = [[PBOpenDocumentCommand alloc] initWithDocumentAbsolutePath:path]; + command.commandTitle = command.displayName; + command.commandDescription = @"Opening document"; + return [command autorelease]; +} + +- (BOOL) validateMenuItem:(NSMenuItem *)menuItem { + BOOL shouldBeEnabled = YES; + SEL action = [menuItem action]; + if (action == @selector(addNewSubmodule)) { + shouldBeEnabled = NO; + //TODO implementation missing + } else { + shouldBeEnabled = [self.submodules count] > 0; + } + return shouldBeEnabled; +} + +@end diff --git a/English.lproj/Preferences.xib b/English.lproj/Preferences.xib index 6aba53d..fd43be8 100644 --- a/English.lproj/Preferences.xib +++ b/English.lproj/Preferences.xib @@ -2,13 +2,13 @@ 1050 - 10H574 - 804 + 10J567 + 851 1038.35 - 461.00 + 462.00 com.apple.InterfaceBuilder.CocoaPlugin - 804 + 851 YES @@ -43,6 +43,37 @@ 268 YES + + + 268 + {{18, 193}, {158, 18}} + + YES + + -2080244224 + 0 + Refresh automatically + + LucidaGrande + 13 + 1044 + + + 1211912703 + 2 + + NSImage + NSSwitch + + + NSSwitch + + + + 200 + 25 + + 268 @@ -53,11 +84,7 @@ 68288064 272630784 Reset all dialog warnings: - - LucidaGrande - 13 - 1044 - + 6 @@ -160,13 +187,8 @@ 1211912703 2 - - NSImage - NSSwitch - - - NSSwitch - + + 200 @@ -274,7 +296,7 @@ 1211912703 2 - + @@ -285,7 +307,7 @@ 268 - {{18, 193}, {279, 18}} + {{18, 218}, {279, 18}} YES @@ -296,7 +318,7 @@ 1211912703 2 - + @@ -307,7 +329,7 @@ 268 - {{18, 218}, {207, 18}} + {{18, 243}, {207, 18}} YES @@ -318,7 +340,7 @@ 1211912703 2 - + @@ -327,7 +349,7 @@ - {400, 254} + {401, 279} NSView @@ -366,7 +388,7 @@ 1211912703 2 - + @@ -506,7 +528,7 @@ - EEEE, MMMM d, yyyy h:mm:ss a + EEEE, dd MMMM, yyyy HH:mm:ss NO @@ -557,7 +579,7 @@ 1211912703 2 - + @@ -573,6 +595,10 @@ SUUpdater + + YES + PBRefreshAutomatically + YES @@ -594,7 +620,7 @@ 1211912703 2 - + @@ -616,7 +642,7 @@ 1211912703 2 - + @@ -638,7 +664,7 @@ 1211912703 2 - + @@ -660,7 +686,7 @@ 1211912703 2 - + @@ -1079,6 +1105,22 @@ 140 + + + value: values.PBRefreshAutomatically + + + + + + value: values.PBRefreshAutomatically + value + values.PBRefreshAutomatically + 2 + + + 144 + @@ -1124,6 +1166,7 @@ + General @@ -1543,6 +1586,20 @@ + + 141 + + + YES + + + + + + 142 + + + @@ -1581,6 +1638,9 @@ 138.IBPluginDependency 139.IBPluginDependency 14.IBPluginDependency + 141.IBPluginDependency + 141.IBViewBoundsToFrameTransform + 142.IBPluginDependency 15.IBEditorWindowLastContentRect 15.IBPluginDependency 16.IBPluginDependency @@ -1623,7 +1683,7 @@ YES com.apple.InterfaceBuilder.CocoaPlugin - {{845, 630}, {400, 254}} + {{511, 548}, {401, 279}} com.apple.InterfaceBuilder.CocoaPlugin YES @@ -1672,6 +1732,11 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAADBcAAAw3QAAA + + com.apple.InterfaceBuilder.CocoaPlugin {{443, 712}, {103, 71}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -1735,7 +1800,7 @@ - 140 + 144 diff --git a/English.lproj/RepositoryWindow.xib b/English.lproj/RepositoryWindow.xib index fd8c769..9b1d7f1 100644 --- a/English.lproj/RepositoryWindow.xib +++ b/English.lproj/RepositoryWindow.xib @@ -2,30 +2,25 @@ 1050 - 10C540 - 759 - 1038.25 - 458.00 + 10F569 + 804 + 1038.29 + 461.00 com.apple.InterfaceBuilder.CocoaPlugin - 759 + 804 YES - + YES com.apple.InterfaceBuilder.CocoaPlugin - YES - - YES - - - YES - + PluginDependencyRecalculationVersion + YES @@ -97,11 +92,9 @@ Clone Repository To - + 268 {{38, 14}, {40, 25}} - - YES -2080244224 @@ -144,11 +137,9 @@ Refresh - + 268 {{8, 14}, {32, 25}} - - YES -2080244224 @@ -344,7 +335,7 @@ 292 - {{0, 1}, {200, 31}} + {{0, 1}, {515, 31}} NSView @@ -399,7 +390,7 @@ - {{364, 0}, {246, 31}} + {{552, 0}, {246, 31}} NSView @@ -535,7 +526,9 @@ YES 0 - + + YES + @@ -598,12 +591,6 @@ Source SplitView - - 352 - - - Content SplitView - 367 @@ -645,26 +632,12 @@ YES - + Status View - - 397 - - - YES - - - - - - 398 - - - 399 @@ -726,6 +699,26 @@ + + 397 + + + YES + + + + + + 398 + + + + + 352 + + + Content SplitView + @@ -745,12 +738,15 @@ 3.windowTemplate.minSize 351.IBPluginDependency 352.IBPluginDependency + 352.IBViewBoundsToFrameTransform 353.IBPluginDependency 367.IBEditorWindowLastContentRect 367.IBPluginDependency 393.IBPluginDependency 396.IBPluginDependency + 396.IBViewBoundsToFrameTransform 397.IBPluginDependency + 397.IBViewBoundsToFrameTransform 398.IBPluginDependency 399.IBPluginDependency 402.IBPluginDependency @@ -767,9 +763,9 @@ YES com.apple.InterfaceBuilder.CocoaPlugin - {{210, 655}, {890, 514}} + {{70, 286}, {890, 514}} com.apple.InterfaceBuilder.CocoaPlugin - {{210, 655}, {890, 514}} + {{70, 286}, {890, 514}} {{15, 196}, {850, 418}} @@ -779,12 +775,21 @@ {600, 450} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + + AUM5AAAAAAAAA + com.apple.InterfaceBuilder.CocoaPlugin {{347, 1169}, {616, 0}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + + AUO2AAAAAAAAA + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABCJAAAwaAAAA + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -820,6 +825,13 @@ YES + + NSApplication + + IBProjectSource + NSApplication+GitXScripting.h + + PBGitWindowController NSWindowController @@ -844,6 +856,45 @@ id + + YES + + YES + cloneTo: + openInTerminal: + refresh: + revealInFinder: + showCommitView: + showHistoryView: + + + YES + + cloneTo: + id + + + openInTerminal: + id + + + refresh: + id + + + revealInFinder: + id + + + showCommitView: + id + + + showHistoryView: + id + + + YES @@ -869,6 +920,55 @@ NSToolbarItem + + YES + + YES + contentSplitView + finderItem + progressIndicator + sourceListControlsView + sourceSplitView + splitView + statusField + terminalItem + + + YES + + contentSplitView + NSView + + + finderItem + NSToolbarItem + + + progressIndicator + NSProgressIndicator + + + sourceListControlsView + NSView + + + sourceSplitView + NSView + + + splitView + NSSplitView + + + statusField + NSTextField + + + terminalItem + NSToolbarItem + + + IBProjectSource PBGitWindowController.h @@ -1228,6 +1328,27 @@ Foundation.framework/Headers/NSURLDownload.h + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CAAnimation.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CALayer.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CIImageProvider.h + + NSObject @@ -1427,6 +1548,13 @@ showWindow: id + + showWindow: + + showWindow: + id + + IBFrameworkSource AppKit.framework/Headers/NSWindowController.h @@ -1456,11 +1584,15 @@ YES CloneRepositoryTemplate + NSMenuCheckmark + NSMenuMixedState NSRefreshTemplate YES {26, 15} + {9, 8} + {7, 2} {10, 12} diff --git a/File Markers/added_file.png b/File Markers/added_file.png new file mode 100644 index 0000000..ad08fae Binary files /dev/null and b/File Markers/added_file.png differ diff --git a/File Markers/conflicted_file.png b/File Markers/conflicted_file.png new file mode 100644 index 0000000..a633ecf Binary files /dev/null and b/File Markers/conflicted_file.png differ diff --git a/File Markers/deleted_file.png b/File Markers/deleted_file.png new file mode 100644 index 0000000..390d96b Binary files /dev/null and b/File Markers/deleted_file.png differ diff --git a/File Markers/ignored_file.png b/File Markers/ignored_file.png new file mode 100644 index 0000000..c4813fb Binary files /dev/null and b/File Markers/ignored_file.png differ diff --git a/File Markers/modified_file.png b/File Markers/modified_file.png new file mode 100644 index 0000000..d5abd30 Binary files /dev/null and b/File Markers/modified_file.png differ diff --git a/File Markers/renamed_file.png b/File Markers/renamed_file.png new file mode 100644 index 0000000..4c294e9 Binary files /dev/null and b/File Markers/renamed_file.png differ diff --git a/File Markers/unversioned_file.png b/File Markers/unversioned_file.png new file mode 100644 index 0000000..62a9361 Binary files /dev/null and b/File Markers/unversioned_file.png differ diff --git a/GLFileView.m b/GLFileView.m index a4b6ba0..1598044 100644 --- a/GLFileView.m +++ b/GLFileView.m @@ -253,7 +253,6 @@ NSArray *stat=[stats objectForKey:fileName]; NSInteger add=[[stat objectAtIndex:0] integerValue]; NSInteger rem=[[stat objectAtIndex:1] integerValue]; - NSInteger tot=add+rem; [res appendString:@""]; [res appendString:[NSString stringWithFormat:@"%@",status,file,fileName,txt]]; @@ -278,8 +277,8 @@ BOOL inDiff=FALSE; BOOL inBlock=FALSE; - int l_int,l_line,l_end; - int r_int,r_line,r_end; + int l_line,l_end; + int r_line,r_end; int i; for (i=0; i<[lines count]; i++) { line=[lines objectAtIndex:i]; @@ -295,12 +294,12 @@ NSArray *pos_l=[[pos objectAtIndex:0] componentsSeparatedByString:@","]; NSArray *pos_r=[[pos objectAtIndex:1] componentsSeparatedByString:@","]; - l_end=l_line=l_int=abs([[pos_l objectAtIndex:0]integerValue]); + l_end=l_line=abs([[pos_l objectAtIndex:0]integerValue]); if ([pos_l count]>1) { l_end=l_line+[[pos_l objectAtIndex:1]integerValue]; } - r_end=r_line=r_int=[[pos_r objectAtIndex:0]integerValue]; + r_end=r_line=[[pos_r objectAtIndex:0]integerValue]; if ([pos_r count]>1) { r_end=r_line+[[pos_r objectAtIndex:1]integerValue]; } @@ -360,8 +359,8 @@ +(NSArray *)getFilesNames:(NSString *)line { - NSString *a; - NSString *b; + NSString *a = nil; + NSString *b = nil; NSScanner *scanner=[NSScanner scannerWithString:line]; if([scanner scanString:@"Binary files " intoString:NULL]){ [scanner scanUpToString:@" and" intoString:&a]; diff --git a/GitX.xcodeproj/project.pbxproj b/GitX.xcodeproj/project.pbxproj index b32a6aa..fbaf896 100644 --- a/GitX.xcodeproj/project.pbxproj +++ b/GitX.xcodeproj/project.pbxproj @@ -24,6 +24,36 @@ 02B41A5E123E307200DFC531 /* PBCommitHookFailedSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = 02B41A5D123E307200DFC531 /* PBCommitHookFailedSheet.m */; }; 02B41A60123E307F00DFC531 /* PBCommitHookFailedSheet.xib in Resources */ = {isa = PBXBuildFile; fileRef = 02B41A5F123E307F00DFC531 /* PBCommitHookFailedSheet.xib */; }; 056438B70ED0C40B00985397 /* DetailViewTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = 056438B60ED0C40B00985397 /* DetailViewTemplate.png */; }; + 21025C1212947AB200D87200 /* sourceListAction.png in Resources */ = {isa = PBXBuildFile; fileRef = 21025C1012947AB200D87200 /* sourceListAction.png */; }; + 21025C1312947AB200D87200 /* sourceListActionOver.png in Resources */ = {isa = PBXBuildFile; fileRef = 21025C1112947AB200D87200 /* sourceListActionOver.png */; }; + 21230CB11284B26A0046E5A1 /* PBGitMenuItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 21230CB01284B26A0046E5A1 /* PBGitMenuItem.m */; }; + 21230D351284C5080046E5A1 /* PBGitStash.m in Sources */ = {isa = PBXBuildFile; fileRef = 21230D341284C5080046E5A1 /* PBGitStash.m */; }; + 21230D821284D1CC0046E5A1 /* stash-icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 21230D811284D1CC0046E5A1 /* stash-icon.png */; }; + 21230D9C128552720046E5A1 /* PBCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 21230D9B128552720046E5A1 /* PBCommand.m */; }; + 21230D9F128552FA0046E5A1 /* PBStashCommandFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 21230D9E128552FA0046E5A1 /* PBStashCommandFactory.m */; }; + 21230DAA1285550B0046E5A1 /* PBCommandMenuItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 21230DA91285550B0046E5A1 /* PBCommandMenuItem.m */; }; + 21230ED21285EB5A0046E5A1 /* PBArgumentPicker.xib in Resources */ = {isa = PBXBuildFile; fileRef = 21230ED11285EB5A0046E5A1 /* PBArgumentPicker.xib */; }; + 21230ED91285EDAF0046E5A1 /* PBArgumentPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 21230ED81285EDAF0046E5A1 /* PBArgumentPicker.m */; }; + 21230EE21285EFB20046E5A1 /* PBArgumentPickerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 21230EE11285EFB20046E5A1 /* PBArgumentPickerController.m */; }; + 21230F7D1285FC6A0046E5A1 /* PBCommandWithParameter.m in Sources */ = {isa = PBXBuildFile; fileRef = 21230F7C1285FC6A0046E5A1 /* PBCommandWithParameter.m */; }; + 212311DD12872BF20046E5A1 /* PBGitSubmodule.m in Sources */ = {isa = PBXBuildFile; fileRef = 212311DC12872BF20046E5A1 /* PBGitSubmodule.m */; }; + 2123121E128735E90046E5A1 /* submodule-notmatching-index.png in Resources */ = {isa = PBXBuildFile; fileRef = 2123121B128735E90046E5A1 /* submodule-notmatching-index.png */; }; + 2123121F128735E90046E5A1 /* submodule-matching-index.png in Resources */ = {isa = PBXBuildFile; fileRef = 2123121C128735E90046E5A1 /* submodule-matching-index.png */; }; + 21231220128735E90046E5A1 /* submodule-empty.png in Resources */ = {isa = PBXBuildFile; fileRef = 2123121D128735E90046E5A1 /* submodule-empty.png */; }; + 2123138A128756ED0046E5A1 /* PBRemoteCommandFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 21231389128756ED0046E5A1 /* PBRemoteCommandFactory.m */; }; + 212313B5128759C00046E5A1 /* PBOpenDocumentCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 212313B4128759C00046E5A1 /* PBOpenDocumentCommand.m */; }; + 212A49A312A31292009DAFAD /* renamed_file.png in Resources */ = {isa = PBXBuildFile; fileRef = 212A49A212A31292009DAFAD /* renamed_file.png */; }; + 212A49A512A312B2009DAFAD /* unversioned_file.png in Resources */ = {isa = PBXBuildFile; fileRef = 212A49A412A312B2009DAFAD /* unversioned_file.png */; }; + 212A49A712A312BE009DAFAD /* added_file.png in Resources */ = {isa = PBXBuildFile; fileRef = 212A49A612A312BE009DAFAD /* added_file.png */; }; + 212A49AA12A31328009DAFAD /* conflicted_file.png in Resources */ = {isa = PBXBuildFile; fileRef = 212A49A812A31328009DAFAD /* conflicted_file.png */; }; + 212A49AB12A31328009DAFAD /* deleted_file.png in Resources */ = {isa = PBXBuildFile; fileRef = 212A49A912A31328009DAFAD /* deleted_file.png */; }; + 212A49AD12A31350009DAFAD /* ignored_file.png in Resources */ = {isa = PBXBuildFile; fileRef = 212A49AC12A31350009DAFAD /* ignored_file.png */; }; + 212A49AF12A3135C009DAFAD /* modified_file.png in Resources */ = {isa = PBXBuildFile; fileRef = 212A49AE12A3135C009DAFAD /* modified_file.png */; }; + 217FF0B912A1CB3300785A65 /* PBStashController.m in Sources */ = {isa = PBXBuildFile; fileRef = 217FF0B312A1CB3300785A65 /* PBStashController.m */; }; + 217FF0BA12A1CB3300785A65 /* PBSubmoduleController.m in Sources */ = {isa = PBXBuildFile; fileRef = 217FF0B512A1CB3300785A65 /* PBSubmoduleController.m */; }; + 217FF0BB12A1CB3300785A65 /* PBGitResetController.m in Sources */ = {isa = PBXBuildFile; fileRef = 217FF0B712A1CB3300785A65 /* PBGitResetController.m */; }; + 217FF0BE12A1CB3E00785A65 /* PBRevealWithFinderCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 217FF0BC12A1CB3E00785A65 /* PBRevealWithFinderCommand.m */; }; + 21CF0B24129C7ED90065B37C /* TrackableOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 21CF0B23129C7ED90065B37C /* TrackableOutlineView.m */; }; 310DC1D81240599E0017A0F7 /* GLFileView.m in Sources */ = {isa = PBXBuildFile; fileRef = 310DC1D71240599E0017A0F7 /* GLFileView.m */; }; 31460CD2124185BA00B90AED /* MGRecessedPopUpButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 31460CA7124185BA00B90AED /* MGRecessedPopUpButtonCell.m */; }; 31460CD3124185BA00B90AED /* MGScopeBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 31460CA9124185BA00B90AED /* MGScopeBar.m */; }; @@ -137,7 +167,6 @@ F56ADDD90ED19F9E002AC78F /* AddBranchTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = F56ADDD70ED19F9E002AC78F /* AddBranchTemplate.png */; }; F56ADDDA0ED19F9E002AC78F /* AddLabelTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = F56ADDD80ED19F9E002AC78F /* AddLabelTemplate.png */; }; F56CC7320E65E0E5004307B4 /* PBGraphCellInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = F56CC7310E65E0E5004307B4 /* PBGraphCellInfo.m */; }; - F57240BB0E9678EA00D8EE66 /* deleted_file.png in Resources */ = {isa = PBXBuildFile; fileRef = F57240BA0E9678EA00D8EE66 /* deleted_file.png */; }; F574A2850EAE2EAC003F2CB1 /* PBRefController.m in Sources */ = {isa = PBXBuildFile; fileRef = F574A2840EAE2EAC003F2CB1 /* PBRefController.m */; }; F574A2910EAE2FF4003F2CB1 /* PBGitConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 93FCCBA80EA8AF450061B02B /* PBGitConfig.m */; }; F57CC3910E05DDF2000472E2 /* PBEasyPipe.m in Sources */ = {isa = PBXBuildFile; fileRef = F57CC3900E05DDF2000472E2 /* PBEasyPipe.m */; }; @@ -251,6 +280,55 @@ 056438B60ED0C40B00985397 /* DetailViewTemplate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = DetailViewTemplate.png; path = Images/DetailViewTemplate.png; sourceTree = ""; }; 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; + 21025C1012947AB200D87200 /* sourceListAction.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = sourceListAction.png; sourceTree = ""; }; + 21025C1112947AB200D87200 /* sourceListActionOver.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = sourceListActionOver.png; sourceTree = ""; }; + 21230CAF1284B26A0046E5A1 /* PBGitMenuItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitMenuItem.h; sourceTree = ""; }; + 21230CB01284B26A0046E5A1 /* PBGitMenuItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitMenuItem.m; sourceTree = ""; }; + 21230D331284C5080046E5A1 /* PBGitStash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitStash.h; sourceTree = ""; }; + 21230D341284C5080046E5A1 /* PBGitStash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitStash.m; sourceTree = ""; }; + 21230D4D1284C92E0046E5A1 /* PBPresentable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBPresentable.h; sourceTree = ""; }; + 21230D811284D1CC0046E5A1 /* stash-icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "stash-icon.png"; sourceTree = ""; }; + 21230D9A128552720046E5A1 /* PBCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBCommand.h; sourceTree = ""; }; + 21230D9B128552720046E5A1 /* PBCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBCommand.m; sourceTree = ""; }; + 21230D9D128552FA0046E5A1 /* PBStashCommandFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBStashCommandFactory.h; sourceTree = ""; }; + 21230D9E128552FA0046E5A1 /* PBStashCommandFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBStashCommandFactory.m; sourceTree = ""; }; + 21230DA0128553120046E5A1 /* PBCommandFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBCommandFactory.h; sourceTree = ""; }; + 21230DA81285550B0046E5A1 /* PBCommandMenuItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBCommandMenuItem.h; sourceTree = ""; }; + 21230DA91285550B0046E5A1 /* PBCommandMenuItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBCommandMenuItem.m; sourceTree = ""; }; + 21230ED11285EB5A0046E5A1 /* PBArgumentPicker.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PBArgumentPicker.xib; sourceTree = ""; }; + 21230ED71285EDAF0046E5A1 /* PBArgumentPicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBArgumentPicker.h; sourceTree = ""; }; + 21230ED81285EDAF0046E5A1 /* PBArgumentPicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBArgumentPicker.m; sourceTree = ""; }; + 21230EE01285EFB20046E5A1 /* PBArgumentPickerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBArgumentPickerController.h; sourceTree = ""; }; + 21230EE11285EFB20046E5A1 /* PBArgumentPickerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBArgumentPickerController.m; sourceTree = ""; }; + 21230F7B1285FC6A0046E5A1 /* PBCommandWithParameter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBCommandWithParameter.h; sourceTree = ""; }; + 21230F7C1285FC6A0046E5A1 /* PBCommandWithParameter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBCommandWithParameter.m; sourceTree = ""; }; + 212311DB12872BF20046E5A1 /* PBGitSubmodule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitSubmodule.h; sourceTree = ""; }; + 212311DC12872BF20046E5A1 /* PBGitSubmodule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitSubmodule.m; sourceTree = ""; }; + 2123121B128735E90046E5A1 /* submodule-notmatching-index.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "submodule-notmatching-index.png"; sourceTree = ""; }; + 2123121C128735E90046E5A1 /* submodule-matching-index.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "submodule-matching-index.png"; sourceTree = ""; }; + 2123121D128735E90046E5A1 /* submodule-empty.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "submodule-empty.png"; sourceTree = ""; }; + 21231388128756ED0046E5A1 /* PBRemoteCommandFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBRemoteCommandFactory.h; sourceTree = ""; }; + 21231389128756ED0046E5A1 /* PBRemoteCommandFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBRemoteCommandFactory.m; sourceTree = ""; }; + 212313B3128759C00046E5A1 /* PBOpenDocumentCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBOpenDocumentCommand.h; sourceTree = ""; }; + 212313B4128759C00046E5A1 /* PBOpenDocumentCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBOpenDocumentCommand.m; sourceTree = ""; }; + 212A49A212A31292009DAFAD /* renamed_file.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = renamed_file.png; sourceTree = ""; }; + 212A49A412A312B2009DAFAD /* unversioned_file.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = unversioned_file.png; sourceTree = ""; }; + 212A49A612A312BE009DAFAD /* added_file.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = added_file.png; sourceTree = ""; }; + 212A49A812A31328009DAFAD /* conflicted_file.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = conflicted_file.png; sourceTree = ""; }; + 212A49A912A31328009DAFAD /* deleted_file.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = deleted_file.png; sourceTree = ""; }; + 212A49AC12A31350009DAFAD /* ignored_file.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ignored_file.png; sourceTree = ""; }; + 212A49AE12A3135C009DAFAD /* modified_file.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = modified_file.png; sourceTree = ""; }; + 217FF0B312A1CB3300785A65 /* PBStashController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBStashController.m; sourceTree = SOURCE_ROOT; }; + 217FF0B412A1CB3300785A65 /* PBStashController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBStashController.h; sourceTree = SOURCE_ROOT; }; + 217FF0B512A1CB3300785A65 /* PBSubmoduleController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBSubmoduleController.m; sourceTree = ""; }; + 217FF0B612A1CB3300785A65 /* PBSubmoduleController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBSubmoduleController.h; sourceTree = ""; }; + 217FF0B712A1CB3300785A65 /* PBGitResetController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitResetController.m; sourceTree = ""; }; + 217FF0B812A1CB3300785A65 /* PBGitResetController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitResetController.h; sourceTree = ""; }; + 217FF0BC12A1CB3E00785A65 /* PBRevealWithFinderCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBRevealWithFinderCommand.m; sourceTree = ""; }; + 217FF0BD12A1CB3E00785A65 /* PBRevealWithFinderCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBRevealWithFinderCommand.h; sourceTree = ""; }; + 21CF0B22129C7ED90065B37C /* TrackableOutlineView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackableOutlineView.h; sourceTree = ""; }; + 21CF0B23129C7ED90065B37C /* TrackableOutlineView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TrackableOutlineView.m; sourceTree = ""; }; + 21CF0B36129C80100065B37C /* CellTrackingRect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CellTrackingRect.h; sourceTree = ""; }; 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; @@ -354,7 +432,7 @@ D8E3B38110DD4E2C001096A3 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/PBCreateTagSheet.xib; sourceTree = ""; }; D8EB6168122F643E00FCCAF4 /* GitXRelativeDateFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GitXRelativeDateFormatter.h; sourceTree = ""; }; D8EB6169122F643E00FCCAF4 /* GitXRelativeDateFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GitXRelativeDateFormatter.m; sourceTree = ""; }; - D8F01C4A12182F19007F729F /* GitX.sdef */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.sdef; path = GitX.sdef; sourceTree = ""; }; + D8F01C4A12182F19007F729F /* GitX.sdef */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = GitX.sdef; sourceTree = ""; }; D8F01D511218A164007F729F /* NSApplication+GitXScripting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSApplication+GitXScripting.h"; sourceTree = ""; }; D8F01D521218A164007F729F /* NSApplication+GitXScripting.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSApplication+GitXScripting.m"; sourceTree = ""; }; D8F01D841218A406007F729F /* GitX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GitX.h; sourceTree = ""; }; @@ -544,6 +622,10 @@ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( + 21230EDF1285EF880046E5A1 /* Controller */, + 21230ED41285ED760046E5A1 /* View */, + 21230D991285524C0046E5A1 /* Commands */, + 21230D321284C4F10046E5A1 /* Model */, ); name = Classes; sourceTree = ""; @@ -584,6 +666,79 @@ name = Products; sourceTree = ""; }; + 21230D321284C4F10046E5A1 /* Model */ = { + isa = PBXGroup; + children = ( + 21230D331284C5080046E5A1 /* PBGitStash.h */, + 21230D341284C5080046E5A1 /* PBGitStash.m */, + 21230D4D1284C92E0046E5A1 /* PBPresentable.h */, + 212311DB12872BF20046E5A1 /* PBGitSubmodule.h */, + 212311DC12872BF20046E5A1 /* PBGitSubmodule.m */, + ); + path = Model; + sourceTree = ""; + }; + 21230D991285524C0046E5A1 /* Commands */ = { + isa = PBXGroup; + children = ( + 217FF0BC12A1CB3E00785A65 /* PBRevealWithFinderCommand.m */, + 217FF0BD12A1CB3E00785A65 /* PBRevealWithFinderCommand.h */, + 21230D9A128552720046E5A1 /* PBCommand.h */, + 21230D9B128552720046E5A1 /* PBCommand.m */, + 21230D9D128552FA0046E5A1 /* PBStashCommandFactory.h */, + 21230D9E128552FA0046E5A1 /* PBStashCommandFactory.m */, + 21230DA0128553120046E5A1 /* PBCommandFactory.h */, + 21230F7B1285FC6A0046E5A1 /* PBCommandWithParameter.h */, + 21230F7C1285FC6A0046E5A1 /* PBCommandWithParameter.m */, + 21231388128756ED0046E5A1 /* PBRemoteCommandFactory.h */, + 21231389128756ED0046E5A1 /* PBRemoteCommandFactory.m */, + 212313B3128759C00046E5A1 /* PBOpenDocumentCommand.h */, + 212313B4128759C00046E5A1 /* PBOpenDocumentCommand.m */, + ); + path = Commands; + sourceTree = ""; + }; + 21230ED41285ED760046E5A1 /* View */ = { + isa = PBXGroup; + children = ( + 21230ED71285EDAF0046E5A1 /* PBArgumentPicker.h */, + 21230ED81285EDAF0046E5A1 /* PBArgumentPicker.m */, + 21CF0B22129C7ED90065B37C /* TrackableOutlineView.h */, + 21CF0B23129C7ED90065B37C /* TrackableOutlineView.m */, + 21CF0B36129C80100065B37C /* CellTrackingRect.h */, + ); + path = View; + sourceTree = ""; + }; + 21230EDF1285EF880046E5A1 /* Controller */ = { + isa = PBXGroup; + children = ( + 217FF0B312A1CB3300785A65 /* PBStashController.m */, + 217FF0B412A1CB3300785A65 /* PBStashController.h */, + 217FF0B512A1CB3300785A65 /* PBSubmoduleController.m */, + 217FF0B612A1CB3300785A65 /* PBSubmoduleController.h */, + 217FF0B712A1CB3300785A65 /* PBGitResetController.m */, + 217FF0B812A1CB3300785A65 /* PBGitResetController.h */, + 21230EE01285EFB20046E5A1 /* PBArgumentPickerController.h */, + 21230EE11285EFB20046E5A1 /* PBArgumentPickerController.m */, + ); + path = Controller; + sourceTree = ""; + }; + 212A499412A3121D009DAFAD /* File Markers */ = { + isa = PBXGroup; + children = ( + 212A49A812A31328009DAFAD /* conflicted_file.png */, + 212A49A912A31328009DAFAD /* deleted_file.png */, + 212A49A612A312BE009DAFAD /* added_file.png */, + 212A49A412A312B2009DAFAD /* unversioned_file.png */, + 212A49A212A31292009DAFAD /* renamed_file.png */, + 212A49AC12A31350009DAFAD /* ignored_file.png */, + 212A49AE12A3135C009DAFAD /* modified_file.png */, + ); + path = "File Markers"; + sourceTree = ""; + }; 29B97314FDCFA39411CA2CEA /* GitTest */ = { isa = PBXGroup; children = ( @@ -611,6 +766,10 @@ 29B97315FDCFA39411CA2CEA /* Other Sources */ = { isa = PBXGroup; children = ( + 212A499412A3121D009DAFAD /* File Markers */, + 2123121B128735E90046E5A1 /* submodule-notmatching-index.png */, + 2123121C128735E90046E5A1 /* submodule-matching-index.png */, + 2123121D128735E90046E5A1 /* submodule-empty.png */, D858108011274D28007F254B /* Branch.png */, D858108111274D28007F254B /* RemoteBranch.png */, D858108211274D28007F254B /* Tag.png */, @@ -629,6 +788,7 @@ F56ADDD70ED19F9E002AC78F /* AddBranchTemplate.png */, F56ADDD80ED19F9E002AC78F /* AddLabelTemplate.png */, 056438B60ED0C40B00985397 /* DetailViewTemplate.png */, + 21230D811284D1CC0046E5A1 /* stash-icon.png */, F57240BA0E9678EA00D8EE66 /* deleted_file.png */, F5E92A1A0E88550E00056E75 /* empty_file.png */, 32CA4F630368D1EE00C91783 /* GitX_Prefix.pch */, @@ -642,6 +802,8 @@ 29B97317FDCFA39411CA2CEA /* Resources */ = { isa = PBXGroup; children = ( + 21025C1012947AB200D87200 /* sourceListAction.png */, + 21025C1112947AB200D87200 /* sourceListActionOver.png */, 02B41A5F123E307F00DFC531 /* PBCommitHookFailedSheet.xib */, F5F7D0641062E7940072C81C /* UpdateKey.pem */, F50A41130EBB872D00208746 /* Widgets */, @@ -663,6 +825,7 @@ D8FDD9F511432A12005647F6 /* PBCloneRepositoryPanel.xib */, 47DBDB680E94EF6500671A1E /* Preferences.xib */, F569AE920F2CBD7C00C2FFA7 /* Credits.html */, + 21230ED11285EB5A0046E5A1 /* PBArgumentPicker.xib */, F58DB55F10566E3900CFDF4A /* PBGitSidebarView.xib */, D8022FE711E124A0003C21F6 /* PBGitXMessageSheet.xib */, ); @@ -786,6 +949,8 @@ D8FDDA63114335E8005647F6 /* PBGitSVRemoteBranchItem.m */, D8FDDA68114335E8005647F6 /* PBGitSVTagItem.h */, D8FDDA69114335E8005647F6 /* PBGitSVTagItem.m */, + 21230CAF1284B26A0046E5A1 /* PBGitMenuItem.h */, + 21230CB01284B26A0046E5A1 /* PBGitMenuItem.m */, D8FDDA60114335E8005647F6 /* PBGitSVOtherRevItem.h */, D8FDDA61114335E8005647F6 /* PBGitSVOtherRevItem.m */, D8FDDA5E114335E8005647F6 /* PBGitSVFolderItem.h */, @@ -982,6 +1147,8 @@ F5FC43C30EBD050800191D80 /* PBRefContextDelegate.h */, F5FC43FC0EBD08EE00191D80 /* PBRefMenuItem.h */, F5FC43FD0EBD08EE00191D80 /* PBRefMenuItem.m */, + 21230DA81285550B0046E5A1 /* PBCommandMenuItem.h */, + 21230DA91285550B0046E5A1 /* PBCommandMenuItem.m */, ); name = History; sourceTree = ""; @@ -1195,7 +1362,6 @@ F52BCE030E84208300AA3741 /* PBGitHistoryView.xib in Resources */, F59116E60E843BB50072CCB1 /* PBGitCommitView.xib in Resources */, F5E92A230E88569500056E75 /* new_file.png in Resources */, - F57240BB0E9678EA00D8EE66 /* deleted_file.png in Resources */, F5E424110EA3E4D60046E362 /* PBDiffWindow.xib in Resources */, F50A411F0EBB874C00208746 /* mainSplitterBar.tiff in Resources */, F50A41200EBB874C00208746 /* mainSplitterDimple.tiff in Resources */, @@ -1234,6 +1400,20 @@ 31460CD5124185BA00B90AED /* Source Code License.rtf in Resources */, 31460CD6124185BA00B90AED /* TODO in Resources */, 02B41A60123E307F00DFC531 /* PBCommitHookFailedSheet.xib in Resources */, + 21230D821284D1CC0046E5A1 /* stash-icon.png in Resources */, + 21230ED21285EB5A0046E5A1 /* PBArgumentPicker.xib in Resources */, + 2123121E128735E90046E5A1 /* submodule-notmatching-index.png in Resources */, + 2123121F128735E90046E5A1 /* submodule-matching-index.png in Resources */, + 21231220128735E90046E5A1 /* submodule-empty.png in Resources */, + 21025C1212947AB200D87200 /* sourceListAction.png in Resources */, + 21025C1312947AB200D87200 /* sourceListActionOver.png in Resources */, + 212A49A312A31292009DAFAD /* renamed_file.png in Resources */, + 212A49A512A312B2009DAFAD /* unversioned_file.png in Resources */, + 212A49A712A312BE009DAFAD /* added_file.png in Resources */, + 212A49AA12A31328009DAFAD /* conflicted_file.png in Resources */, + 212A49AB12A31328009DAFAD /* deleted_file.png in Resources */, + 212A49AD12A31350009DAFAD /* ignored_file.png in Resources */, + 212A49AF12A3135C009DAFAD /* modified_file.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1387,6 +1567,22 @@ 31460CD2124185BA00B90AED /* MGRecessedPopUpButtonCell.m in Sources */, 31460CD3124185BA00B90AED /* MGScopeBar.m in Sources */, 02B41A5E123E307200DFC531 /* PBCommitHookFailedSheet.m in Sources */, + 21230CB11284B26A0046E5A1 /* PBGitMenuItem.m in Sources */, + 21230D351284C5080046E5A1 /* PBGitStash.m in Sources */, + 21230D9C128552720046E5A1 /* PBCommand.m in Sources */, + 21230D9F128552FA0046E5A1 /* PBStashCommandFactory.m in Sources */, + 21230DAA1285550B0046E5A1 /* PBCommandMenuItem.m in Sources */, + 21230ED91285EDAF0046E5A1 /* PBArgumentPicker.m in Sources */, + 21230EE21285EFB20046E5A1 /* PBArgumentPickerController.m in Sources */, + 21230F7D1285FC6A0046E5A1 /* PBCommandWithParameter.m in Sources */, + 212311DD12872BF20046E5A1 /* PBGitSubmodule.m in Sources */, + 2123138A128756ED0046E5A1 /* PBRemoteCommandFactory.m in Sources */, + 212313B5128759C00046E5A1 /* PBOpenDocumentCommand.m in Sources */, + 21CF0B24129C7ED90065B37C /* TrackableOutlineView.m in Sources */, + 217FF0B912A1CB3300785A65 /* PBStashController.m in Sources */, + 217FF0BA12A1CB3300785A65 /* PBSubmoduleController.m in Sources */, + 217FF0BB12A1CB3300785A65 /* PBGitResetController.m in Sources */, + 217FF0BE12A1CB3E00785A65 /* PBRevealWithFinderCommand.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1608,10 +1804,12 @@ GCC_ENABLE_OBJC_GC = required; GCC_PREPROCESSOR_DEFINITIONS = DEBUG; GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = DEBUG_BUILD; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_PREPROCESS = YES; PREBINDING = NO; + RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; }; name = Debug; @@ -1625,11 +1823,13 @@ x86_64, ); GCC_ENABLE_OBJC_GC = required; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_PREFIX_HEADER = $PROJECT_TEMP_DIR/revision; INFOPLIST_PREPROCESS = YES; PREBINDING = NO; + RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; }; name = Release; diff --git a/Model/PBGitStash.h b/Model/PBGitStash.h new file mode 100644 index 0000000..9d5eba5 --- /dev/null +++ b/Model/PBGitStash.h @@ -0,0 +1,25 @@ +// +// PBGitStash.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBPresentable.h" + +@interface PBGitStash : NSObject { + NSString *stashRawString; + + NSString *stashSourceMessage; + NSString *name; + NSString *message; +} +@property (nonatomic, retain, readonly) NSString *name; +@property (nonatomic, retain, readonly) NSString *message; +@property (nonatomic, retain, readonly) NSString *stashSourceMessage; +@property (nonatomic, retain, readonly) NSString *stashRawString; + +- initWithRawStashLine:(NSString *) stashLineFromStashListOutput; +@end diff --git a/Model/PBGitStash.m b/Model/PBGitStash.m new file mode 100644 index 0000000..a042413 --- /dev/null +++ b/Model/PBGitStash.m @@ -0,0 +1,55 @@ +// +// PBGitStash.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBGitStash.h" + + +@implementation PBGitStash +@synthesize name; +@synthesize message; +@synthesize stashRawString; +@synthesize stashSourceMessage; + +- initWithRawStashLine:(NSString *) stashLineFromStashListOutput { + if (self = [super init]) { + stashRawString = [stashLineFromStashListOutput retain]; + NSArray *lineComponents = [stashLineFromStashListOutput componentsSeparatedByString:@":"]; + name = [[lineComponents objectAtIndex:0] retain]; + stashSourceMessage = [[[lineComponents objectAtIndex:1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] retain]; + message = [[[lineComponents objectAtIndex:2] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] retain]; + } + return self; +} + +- (void) dealloc { + [stashSourceMessage release]; + [stashRawString release]; + [name release]; + [message release]; + [super dealloc]; +} + +- (NSString *) description { + return self.stashRawString; +} + +#pragma mark Presentable + +- (NSString *) displayDescription { + return [NSString stringWithFormat:@"%@ (%@)", self.message, self.name]; +} + +- (NSString *) popupDescription { + return [self description]; +} + +- (NSImage *) icon { + return [NSImage imageNamed:@"stash-icon.png"]; +} + +@end diff --git a/Model/PBGitSubmodule.h b/Model/PBGitSubmodule.h new file mode 100644 index 0000000..5d1db18 --- /dev/null +++ b/Model/PBGitSubmodule.h @@ -0,0 +1,39 @@ +// +// PBGitSubmodule.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-07. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBPresentable.h" + +typedef enum { + PBGitSubmoduleStateNotInitialized, + PBGitSubmoduleStateMatchingIndex, + PBGitSubmoduleStateDoesNotMatchIndex, +} PBGitSubmoduleState; + +@interface PBGitSubmodule : NSObject { + NSString *name; + NSString *path; + NSString *checkedOutCommit; + + PBGitSubmoduleState submoduleState; + + NSMutableArray *submodules; +} +@property (nonatomic, retain, readonly) NSMutableArray *submodules; +@property (nonatomic, assign, readonly) PBGitSubmoduleState submoduleState; +@property (nonatomic, retain, readonly) NSString *name; +@property (nonatomic, retain, readonly) NSString *path; +@property (nonatomic, retain, readonly) NSString *checkedOutCommit; + +- (id) initWithRawSubmoduleStatusString:(NSString *) submoduleStatusString; + ++ (NSImage *) imageForSubmoduleState:(PBGitSubmoduleState) state; ++ (PBGitSubmoduleState) submoduleStateFromCharacter:(unichar) character; + +- (void) addSubmodule:(PBGitSubmodule *) submodule; +@end diff --git a/Model/PBGitSubmodule.m b/Model/PBGitSubmodule.m new file mode 100644 index 0000000..cea00d0 --- /dev/null +++ b/Model/PBGitSubmodule.m @@ -0,0 +1,126 @@ +// +// PBGitSubmodule.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-07. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBGitSubmodule.h" + +@interface PBGitSubmodule() +@property (nonatomic, retain) NSString *name; +@property (nonatomic, retain) NSString *path; +@property (nonatomic, retain) NSString *checkedOutCommit; +@end + + +@implementation PBGitSubmodule +@synthesize name; +@synthesize path; +@synthesize checkedOutCommit; +@synthesize submoduleState; +@synthesize submodules; + +- (NSMutableArray *) submodules { + if (!submodules) { + submodules = [[NSMutableArray alloc] init]; + } + return submodules; +} + +- (id) initWithRawSubmoduleStatusString:(NSString *) submoduleStatusString { + NSParameterAssert([submoduleStatusString length] > 0); + + if (self = [super init]) { + unichar status = [submoduleStatusString characterAtIndex:0]; + submoduleState = [PBGitSubmodule submoduleStateFromCharacter:status]; + NSScanner *scanner = [NSScanner scannerWithString:[submoduleStatusString substringFromIndex:1]]; + NSString *sha1 = nil; + NSString *fullPath = nil; + NSString *coName = nil; + BOOL shouldContinue = [scanner scanUpToString:@" " intoString:&sha1]; + if (shouldContinue) { + shouldContinue = [scanner scanUpToString:@"(" intoString:&fullPath]; + } + if (shouldContinue) { + shouldContinue = [scanner scanString:@"(" intoString:NULL]; + } + if (shouldContinue) { + shouldContinue = [scanner scanUpToString:@")" intoString:&coName]; + } + self.path = [fullPath stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + coName = [coName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + self.checkedOutCommit = [coName length] > 0 ? coName : nil; + self.name = [self.path lastPathComponent]; + + } + return self; +} + +- (void) dealloc { + [submodules release]; + [name release]; + [path release]; + [checkedOutCommit release]; + [super dealloc]; +} + +- (void) addSubmodule:(PBGitSubmodule *) submodule { + [self.submodules addObject:submodule]; +} + +#pragma mark - +#pragma mark Presentable + +- (NSImage *) icon { + return [PBGitSubmodule imageForSubmoduleState:self.submoduleState]; +} + +- (NSString *) displayDescription { + NSMutableString *result = [[NSMutableString alloc] initWithString:self.name]; + if (self.checkedOutCommit) { + [result appendFormat:@" (%@)", self.checkedOutCommit]; + } + return [result autorelease]; +} + +- (NSString *) popupDescription { + return [self description]; +} + + +#pragma mark - +#pragma mark Private + ++ (NSImage *) imageForSubmoduleState:(PBGitSubmoduleState) state { + NSString *imageName = nil; + + if (state == PBGitSubmoduleStateMatchingIndex) { + imageName = @"submodule-matching-index.png"; + } else if (state == PBGitSubmoduleStateNotInitialized) { + imageName = @"submodule-empty.png"; + } else if (state == PBGitSubmoduleStateDoesNotMatchIndex) { + imageName = @"submodule-notmatching-index.png"; + } + + return [NSImage imageNamed:imageName]; +} + ++ (PBGitSubmoduleState) submoduleStateFromCharacter:(unichar) character { + PBGitSubmoduleState state = PBGitSubmoduleStateMatchingIndex; + if (character == '-') { + state = PBGitSubmoduleStateNotInitialized; + } else if (character == '+') { + state = PBGitSubmoduleStateDoesNotMatchIndex; + } else if (character != ' ') { + NSAssert1(NO, @"Ooops unsupported submodule status character: %c", character); + } + + return state; +} + +- (NSString *) description { + return [NSString stringWithFormat:@"[SUBMODULE] %@(%@) %@", self.name, self.path, self.checkedOutCommit]; +} +@end diff --git a/Model/PBPresentable.h b/Model/PBPresentable.h new file mode 100644 index 0000000..4c6cf70 --- /dev/null +++ b/Model/PBPresentable.h @@ -0,0 +1,14 @@ +// +// PBPresentable.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + + +@protocol PBPresentable +- (NSImage *) icon; +- (NSString *) displayDescription; +- (NSString *) popupDescription; +@end diff --git a/PBArgumentPicker.xib b/PBArgumentPicker.xib new file mode 100644 index 0000000..aae90bc --- /dev/null +++ b/PBArgumentPicker.xib @@ -0,0 +1,1110 @@ + + + + 1050 + 10F569 + 804 + 1038.29 + 461.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 804 + + + YES + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + YES + + + YES + + + + YES + + PBArgumentPickerController + + + FirstResponder + + + NSApplication + + + 1 + 2 + {{716, 798}, {297, 125}} + 611845120 + Window + NSWindow + + {1.79769e+308, 1.79769e+308} + + + 256 + + YES + + + 268 + {{187, 8}, {96, 32}} + + YES + + 67239424 + 134217728 + OK + + LucidaGrande + 13 + 1044 + + + -2034876161 + 65 + + + DQ + 200 + 25 + + + + + 268 + {{25, 67}, {252, 22}} + + YES + + -1804468671 + 272630784 + + + + YES + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 6 + System + textColor + + 3 + MAA + + + + + + + 268 + {{91, 8}, {96, 32}} + + YES + + 67239424 + 134217728 + Cancel + + + -2038284033 + 129 + + Gw + 200 + 25 + + + + + 268 + {{22, 97}, {258, 17}} + + YES + + 68288064 + 272630784 + Provide stash message: + + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2NjY3AA + + + + 6 + System + controlTextColor + + + + + + {297, 125} + + + {{0, 0}, {1680, 1028}} + {1.79769e+308, 1.79769e+308} + + + + + YES + + + okClicked: + + + + 34 + + + + window + + + + 37 + + + + cancelButton + + + + 38 + + + + label + + + + 39 + + + + okButton + + + + 40 + + + + textField + + + + 41 + + + + view + + + + 42 + + + + cancelClicked: + + + + 43 + + + + + YES + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 35 + + + YES + + + + + + 36 + + + YES + + + + + + + + + 16 + + + YES + + + + + + 17 + + + + + 18 + + + YES + + + + + + 19 + + + + + 24 + + + YES + + + + + + 25 + + + + + 26 + + + YES + + + + + + 27 + + + + + + + YES + + YES + 16.IBPluginDependency + 16.IBViewBoundsToFrameTransform + 17.IBPluginDependency + 18.IBPluginDependency + 18.IBViewBoundsToFrameTransform + 19.IBPluginDependency + 24.IBPluginDependency + 24.IBViewBoundsToFrameTransform + 25.IBPluginDependency + 26.IBPluginDependency + 26.IBViewBoundsToFrameTransform + 27.IBPluginDependency + 35.IBEditorWindowLastContentRect + 35.IBPluginDependency + 35.IBWindowTemplateEditedContentRect + 35.NSWindowTemplate.visibleAtLaunch + 35.windowTemplate.hasMaxSize + 35.windowTemplate.hasMinSize + 35.windowTemplate.maxSize + 35.windowTemplate.minSize + 36.CustomClassName + 36.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDOwAAwiAAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABByAAAwrIAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABCtgAAwiAAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABBsAAAwuQAAA + + com.apple.InterfaceBuilder.CocoaPlugin + {{716, 798}, {297, 125}} + com.apple.InterfaceBuilder.CocoaPlugin + {{716, 798}, {297, 125}} + + + + {297, 125} + {297, 125} + PBArgumentPicker + com.apple.InterfaceBuilder.CocoaPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 43 + + + + YES + + NSApplication + + IBProjectSource + NSApplication+GitXScripting.h + + + + PBArgumentPicker + NSView + + YES + + YES + cancelButton + label + okButton + textField + + + YES + NSButton + NSTextField + NSButton + NSTextField + + + + YES + + YES + cancelButton + label + okButton + textField + + + YES + + cancelButton + NSButton + + + label + NSTextField + + + okButton + NSButton + + + textField + NSTextField + + + + + IBProjectSource + View/PBArgumentPicker.h + + + + PBArgumentPickerController + NSWindowController + + YES + + YES + cancelClicked: + okClicked: + + + YES + id + id + + + + YES + + YES + cancelClicked: + okClicked: + + + YES + + cancelClicked: + id + + + okClicked: + id + + + + + view + PBArgumentPicker + + + view + + view + PBArgumentPicker + + + + IBProjectSource + Controller/PBArgumentPickerController.h + + + + + YES + + NSActionCell + NSCell + + IBFrameworkSource + AppKit.framework/Headers/NSActionCell.h + + + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSUserInterfaceItemSearching.h + + + + NSButton + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSButton.h + + + + NSButtonCell + NSActionCell + + IBFrameworkSource + AppKit.framework/Headers/NSButtonCell.h + + + + NSCell + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSCell.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDictionaryController.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObjectScripting.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPortCoder.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptObjectSpecifiers.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptWhoseTests.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLDownload.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CAAnimation.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CALayer.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CIImageProvider.h + + + + NSObject + + IBFrameworkSource + ScriptingBridge.framework/Headers/SBApplication.h + + + + NSObject + + IBFrameworkSource + Sparkle.framework/Headers/SUAppcast.h + + + + NSObject + + IBFrameworkSource + Sparkle.framework/Headers/SUUpdater.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebDownload.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebEditingDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebFrameLoadDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebJavaPlugIn.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebPlugin.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebPluginContainer.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebPolicyDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebResourceLoadDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebScriptObject.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebUIDelegate.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSTextField + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSTextField.h + + + + NSTextFieldCell + NSActionCell + + IBFrameworkSource + AppKit.framework/Headers/NSTextFieldCell.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSDrawer.h + + + + NSWindow + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSWindowScripting.h + + + + NSWindowController + NSResponder + + showWindow: + id + + + showWindow: + + showWindow: + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSWindowController.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + GitX.xcodeproj + 3 + + diff --git a/PBChangedFile.h b/PBChangedFile.h index bffc110..ca3e160 100644 --- a/PBChangedFile.h +++ b/PBChangedFile.h @@ -12,7 +12,8 @@ typedef enum { NEW, MODIFIED, - DELETED + DELETED, + ADDED } PBChangedFileStatus; @interface PBChangedFile : NSObject { @@ -35,5 +36,6 @@ typedef enum { - (NSImage *)icon; - (NSString *)indexInfo; ++ (NSImage *) iconForStatus:(PBChangedFileStatus) aStatus; - (id) initWithPath:(NSString *)p; @end diff --git a/PBChangedFile.m b/PBChangedFile.m index ac9b4d3..5a7492e 100644 --- a/PBChangedFile.m +++ b/PBChangedFile.m @@ -31,24 +31,31 @@ return [NSString stringWithFormat:@"%@ %@\t%@\0", self.commitBlobMode, self.commitBlobSHA, self.path]; } -- (NSImage *) icon -{ ++ (NSImage *) iconForStatus:(PBChangedFileStatus) aStatus { NSString *filename; - switch (status) { + switch (aStatus) { case NEW: - filename = @"new_file"; + filename = @"unversioned_file"; break; case DELETED: filename = @"deleted_file"; break; + case ADDED: + filename = @"added_file"; + break; default: - filename = @"empty_file"; + filename = @"modified_file"; break; } NSString *p = [[NSBundle mainBundle] pathForResource:filename ofType:@"png"]; return [[NSImage alloc] initByReferencingFile: p]; } +- (NSImage *) icon +{ + return [PBChangedFile iconForStatus:status]; +} + + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector { return NO; diff --git a/PBCommandMenuItem.h b/PBCommandMenuItem.h new file mode 100644 index 0000000..62ac0fd --- /dev/null +++ b/PBCommandMenuItem.h @@ -0,0 +1,19 @@ +// +// PBCommandMenuItem.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBCommand.h" + +@interface PBCommandMenuItem : NSMenuItem { + PBCommand *command; +} +@property (nonatomic, retain, readonly) PBCommand *command; + +- initWithCommand:(PBCommand *) aCommand; + +@end diff --git a/PBCommandMenuItem.m b/PBCommandMenuItem.m new file mode 100644 index 0000000..50becd2 --- /dev/null +++ b/PBCommandMenuItem.m @@ -0,0 +1,37 @@ +// +// PBCommandMenuItem.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBCommandMenuItem.h" + +@interface PBCommandMenuItem() +@property (nonatomic, retain) PBCommand *command; +@end + + + +@implementation PBCommandMenuItem +@synthesize command; + +- initWithCommand:(PBCommand *) aCommand { + if (self = [super init]) { + self.command = aCommand; + super.title = [aCommand displayName]; + [self setTarget:aCommand]; + [self setAction:@selector(invoke)]; + [self setEnabled:[aCommand canBeFired]]; + } + return self; +} + +- (void) dealloc { + [command release]; + [super dealloc]; +} + + +@end diff --git a/PBEasyPipe.m b/PBEasyPipe.m index 8506daf..fe8efa8 100644 --- a/PBEasyPipe.m +++ b/PBEasyPipe.m @@ -18,9 +18,17 @@ + (NSTask *) taskForCommand:(NSString *)cmd withArgs:(NSArray *)args inDir:(NSString *)dir { + NSMutableArray *filteredArguments = [[NSMutableArray alloc] init]; + for (NSString *param in args) { + if ([param length] > 0) { + [filteredArguments addObject:param]; + } + } + NSTask* task = [[NSTask alloc] init]; [task setLaunchPath:cmd]; - [task setArguments:args]; + [task setArguments:filteredArguments]; + [filteredArguments release]; if (dir) [task setCurrentDirectoryPath:dir]; diff --git a/PBGitCommitView.xib b/PBGitCommitView.xib index 89d807c..9d1f889 100644 --- a/PBGitCommitView.xib +++ b/PBGitCommitView.xib @@ -21,7 +21,6 @@ YES - YES @@ -84,6 +83,7 @@ {852, 181} + @@ -138,6 +138,7 @@ 4352 {189, 221} + YES @@ -230,6 +231,7 @@ {{1, 1}, {189, 221}} + @@ -240,6 +242,7 @@ -2147483392 {{174, 1}, {15, 178}} + _doScroller: 0.99337750000000002 @@ -249,6 +252,7 @@ -2147483392 {{1, 179}, {173, 15}} + 1 _doScroller: @@ -257,6 +261,7 @@ {{-1, -1}, {191, 223}} + 562 @@ -267,10 +272,12 @@ {190, 227} + {190, 242} + {0, 0} 67239424 @@ -309,6 +316,7 @@ 289 {{339, 0}, {96, 32}} + YES 67239424 @@ -321,7 +329,7 @@ -2038284033 - 301990017 + 268435585 DQ 200 @@ -367,6 +375,7 @@ {{0, 27}, {427, 14}} + @@ -441,6 +450,7 @@ {{1, 1}, {427, 184}} + @@ -455,6 +465,7 @@ -2147483392 {{346, 1}, {15, 164}} + _doScroller: 0.99166670000000001 @@ -464,6 +475,7 @@ -2147483392 {{-100, -100}, {87, 18}} + 1 _doScroller: @@ -473,6 +485,7 @@ {{0, 36}, {429, 186}} + 530 @@ -484,6 +497,7 @@ 292 {{-2, 9}, {82, 18}} + YES -2080244224 @@ -511,6 +525,7 @@ 289 {{243, 0}, {96, 32}} + YES 67239424 @@ -529,10 +544,12 @@ {429, 227} + {{199, 0}, {429, 242}} + {0, 0} 67239424 @@ -576,6 +593,7 @@ 4352 {214, 221} + 1 YES @@ -629,6 +647,7 @@ {{1, 1}, {214, 221}} + @@ -639,6 +658,7 @@ -2147483392 {{257, 1}, {15, 246}} + _doScroller: 0.99519230000000003 @@ -648,6 +668,7 @@ -2147483392 {{1, 247}, {256, 15}} + 1 _doScroller: @@ -656,6 +677,7 @@ {{0, -1}, {216, 223}} + 562 @@ -666,10 +688,12 @@ {215, 227} + {{637, 0}, {215, 242}} + {0, 0} 67239424 @@ -691,6 +715,7 @@ {{0, 190}, {852, 242}} + YES @@ -700,6 +725,7 @@ {852, 432} + NSView @@ -1375,7 +1401,7 @@ YES com.apple.InterfaceBuilder.CocoaPlugin - {{1091, 655}, {852, 432}} + {{393, 574}, {852, 432}} com.apple.InterfaceBuilder.CocoaPlugin diff --git a/PBGitConfig.h b/PBGitConfig.h index 1645819..43b63e9 100644 --- a/PBGitConfig.h +++ b/PBGitConfig.h @@ -16,4 +16,8 @@ - init; - initWithRepositoryPath:(NSString *)path; + +// get config data: `git config -l` +- (NSDictionary*) listConfigValuesInDir:(NSString*)inDir; + @end diff --git a/PBGitConfig.m b/PBGitConfig.m index caf883c..4bdbbc7 100644 --- a/PBGitConfig.m +++ b/PBGitConfig.m @@ -88,4 +88,37 @@ // It doesn't exist at all. Write it locally. [self writeValue:value forKey:path global:NO]; } + +/** + runs `git config -l` returning a dict of key-value pairs from the result + + passing nil as directory passes '--global' flag + */ +- (NSDictionary*) listConfigValuesInDir:(NSString*)inDir +{ + NSArray* arguments; + + if (inDir == nil) { + arguments = [NSArray arrayWithObjects:@"config", @"--global", @"-l", nil]; + } else { + arguments = [NSArray arrayWithObjects:@"config", @"-l", nil]; + } + + int ret = 1; + NSString* output = [PBEasyPipe outputForCommand:[PBGitBinary path] withArgs:arguments inDir:inDir retValue:&ret]; + NSMutableDictionary *result = [NSMutableDictionary dictionary]; + if (ret==0) { + NSArray *lines = [output componentsSeparatedByString:@"\n"]; + + for (NSString* line in lines) { + NSRange equalsPos = [line rangeOfString:@"="]; + NSString* key = [line substringToIndex:equalsPos.location]; + NSString* value = [line substringFromIndex:equalsPos.location+1]; + [result setObject:value forKey:key]; + } + } + + return [NSDictionary dictionaryWithDictionary:result]; +} + @end diff --git a/PBGitDefaults.h b/PBGitDefaults.h index a95b524..6fff110 100644 --- a/PBGitDefaults.h +++ b/PBGitDefaults.h @@ -18,6 +18,7 @@ + (BOOL) confirmPublicGists; + (BOOL) isGistPublic; + (BOOL)showWhitespaceDifferences; ++ (BOOL)refreshAutomatically; + (BOOL)openCurDirOnLaunch; + (BOOL)showOpenPanelOnLaunch; + (BOOL) shouldCheckoutBranch; @@ -41,4 +42,5 @@ + (BOOL)isDialogWarningSuppressedForDialog:(NSString *)dialog; + (void)resetAllDialogWarnings; + @end diff --git a/PBGitDefaults.m b/PBGitDefaults.m index 5656469..f6af844 100644 --- a/PBGitDefaults.m +++ b/PBGitDefaults.m @@ -17,6 +17,7 @@ #define kConfirmPublicGists @"PBConfirmPublicGists" #define kPublicGist @"PBGistPublic" #define kShowWhitespaceDifferences @"PBShowWhitespaceDifferences" +#define kRefreshAutomatically @"PBRefreshAutomatically" #define kOpenCurDirOnLaunch @"PBOpenCurDirOnLaunch" #define kShowOpenPanelOnLaunch @"PBShowOpenPanelOnLaunch" #define kShouldCheckoutBranch @"PBShouldCheckoutBranch" @@ -28,6 +29,7 @@ #define kHistorySearchMode @"PBHistorySearchMode" #define kSuppressedDialogWarnings @"Suppressed Dialog Warnings" + @implementation PBGitDefaults + (void)initialize @@ -38,19 +40,21 @@ [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:kCommitMessageViewHasVerticalLine]; [defaultValues setObject:[NSNumber numberWithBool:YES] - forKey:kEnableGist]; + forKey:kEnableGist]; [defaultValues setObject:[NSNumber numberWithBool:YES] - forKey:kEnableGravatar]; + forKey:kEnableGravatar]; [defaultValues setObject:[NSNumber numberWithBool:YES] - forKey:kConfirmPublicGists]; + forKey:kConfirmPublicGists]; [defaultValues setObject:[NSNumber numberWithBool:NO] - forKey:kPublicGist]; + forKey:kPublicGist]; [defaultValues setObject:[NSNumber numberWithBool:YES] - forKey:kShowWhitespaceDifferences]; + forKey:kShowWhitespaceDifferences]; [defaultValues setObject:[NSNumber numberWithBool:YES] - forKey:kOpenCurDirOnLaunch]; + forKey:kRefreshAutomatically]; [defaultValues setObject:[NSNumber numberWithBool:YES] - forKey:kShowOpenPanelOnLaunch]; + forKey:kOpenCurDirOnLaunch]; + [defaultValues setObject:[NSNumber numberWithBool:YES] + forKey:kShowOpenPanelOnLaunch]; [defaultValues setObject:[NSNumber numberWithBool:YES] forKey:kShouldCheckoutBranch]; [defaultValues setObject:[NSNumber numberWithBool:NO] @@ -90,10 +94,15 @@ return [[NSUserDefaults standardUserDefaults] boolForKey:kPublicGist]; } -+ (BOOL)showWhitespaceDifferences ++ (BOOL) showWhitespaceDifferences { return [[NSUserDefaults standardUserDefaults] boolForKey:kShowWhitespaceDifferences]; } + ++ (BOOL) refreshAutomatically +{ + return [[NSUserDefaults standardUserDefaults] boolForKey:kRefreshAutomatically]; +} + (BOOL)openCurDirOnLaunch { diff --git a/PBGitGrapher.mm b/PBGitGrapher.mm index 827c632..41401d6 100644 --- a/PBGitGrapher.mm +++ b/PBGitGrapher.mm @@ -172,4 +172,3 @@ void add_line(struct PBGitGraphLine *lines, int *nLines, int upper, int from, in [super finalize]; } @end -djhfgjdshfjkds diff --git a/PBGitHistoryController.m b/PBGitHistoryController.m index c4037c2..e3be741 100644 --- a/PBGitHistoryController.m +++ b/PBGitHistoryController.m @@ -25,6 +25,7 @@ #import "PBQLTextView.h" #import "GLFileView.h" +#import "PBSourceViewCell.h" #define kHistorySelectedDetailIndexKey @"PBHistorySelectedDetailIndex" #define kHistoryDetailViewIndex 0 @@ -89,8 +90,10 @@ [scopeBarView setTopColor:[NSColor colorWithCalibratedHue:0.579 saturation:0.068 brightness:0.898 alpha:1.000] bottomColor:[NSColor colorWithCalibratedHue:0.579 saturation:0.119 brightness:0.765 alpha:1.000]]; [self updateBranchFilterMatrix]; + [super awakeFromNib]; + [fileBrowser setDelegate:self]; } - (void)updateKeys @@ -798,4 +801,15 @@ return iconRect; } +- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(PBSourceViewCell *)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item +{ + NSWorkspace *workspace = [NSWorkspace sharedWorkspace]; + PBGitTree *object = [item representedObject]; + NSString *workingDirectory = [[repository workingDirectory] stringByAppendingString:@"/"]; + NSString *path = [workingDirectory stringByAppendingPathComponent:[object fullPath]]; + NSImage *image = [workspace iconForFile:path]; + [image setSize:NSMakeSize(15, 15)]; + [cell setImage:image]; +} + @end diff --git a/PBGitHistoryView.xib b/PBGitHistoryView.xib index ad42aa9..3d02796 100644 --- a/PBGitHistoryView.xib +++ b/PBGitHistoryView.xib @@ -113,6 +113,7 @@ 292 {{267, 3}, {71, 25}} + YES -2080244224 @@ -155,6 +156,7 @@ 268 {{206, 3}, {37, 25}} + YES -2080244224 @@ -179,6 +181,7 @@ 268 {{161, 3}, {37, 25}} + YES -2080244224 @@ -203,6 +206,7 @@ 268 {{116, 3}, {37, 25}} + YES -2080244224 @@ -227,6 +231,7 @@ 268 {{55, 3}, {37, 25}} + YES -2080244224 @@ -251,6 +256,7 @@ 268 {{10, 3}, {37, 25}} + YES -2080244224 @@ -275,6 +281,7 @@ 10 {{0, -2}, {955, 5}} + {0, 0} 67239424 @@ -303,6 +310,7 @@ {{0, 404}, {955, 30}} + PBGitGradientBarView @@ -320,6 +328,7 @@ 10 {{0, 144}, {955, 5}} + {0, 0} 67239424 @@ -352,12 +361,14 @@ 4352 {955, 130} + YES 256 {955, 17} + @@ -365,6 +376,7 @@ -2147483392 {{-26, 0}, {16, 17}} + YES @@ -491,7 +503,7 @@ - MMMM d, yyyy h:mm a + d MMMM yyyy HH:mm NO @@ -620,6 +632,7 @@ {{0, 17}, {955, 130}} + @@ -630,6 +643,7 @@ -2147483392 {{837, 17}, {15, 179}} + _doScroller: 0.87603306770324707 @@ -639,6 +653,7 @@ -2147483392 {{0, 123}, {852, 15}} + 1 _doScroller: @@ -654,6 +669,7 @@ {955, 17} + @@ -663,6 +679,7 @@ {955, 147} + 560 @@ -683,6 +700,7 @@ {{740, 3}, {16, 16}} + 20746 100 @@ -691,6 +709,7 @@ 265 {{765, 2}, {180, 19}} + YES 343014976 @@ -752,6 +771,7 @@ 265 {{714, 3}, {43, 18}} + YES 67239424 @@ -788,6 +808,7 @@ 265 {{630, 5}, {80, 14}} + YES 68288064 @@ -809,6 +830,7 @@ 268 {{49, 2}, {57, 17}} + 1 YES @@ -834,6 +856,7 @@ 268 {{114, 2}, {103, 17}} + 2 YES @@ -855,6 +878,7 @@ 268 {{11, 2}, {30, 17}} + YES 67239424 @@ -873,11 +897,13 @@ {{0, 147}, {955, 24}} + PBGitGradientBarView {955, 171} + NSView @@ -890,6 +916,7 @@ 18 {955, 233} + YES @@ -983,6 +1010,7 @@ 4368 {216, 233} + YES @@ -1037,6 +1065,7 @@ {{1, 1}, {216, 233}} + @@ -1047,6 +1076,7 @@ 256 {{217, 1}, {15, 233}} + _doScroller: 0.99481862783432007 @@ -1056,6 +1086,7 @@ -2147483392 {{-100, -100}, {502, 15}} + 1 _doScroller: @@ -1065,6 +1096,7 @@ {233, 235} + 18 @@ -1092,6 +1124,7 @@ 289 {{41, 1.5}, {29, 19}} + YES -2080244224 @@ -1118,11 +1151,13 @@ {{639, 0}, {84, 24}} + NSView {{0, 211}, {723, 24}} + MGScopeBar @@ -1151,6 +1186,7 @@ {723, 210} + @@ -1161,17 +1197,20 @@ {{234, 0}, {723, 235}} + NSView {{-1, -1}, {957, 235}} + YES 2 {955, 233} + Tree @@ -1191,16 +1230,19 @@ {{0, 172}, {955, 233}} + NSView {955, 405} + 2 {955, 434} + NSView @@ -2633,6 +2675,7 @@ 16.IBPluginDependency 17.IBPluginDependency 18.IBPluginDependency + 19.CustomClassName 19.IBPluginDependency 2.CustomClassName 2.IBEditorWindowLastContentRect @@ -2681,6 +2724,7 @@ 333.IBPluginDependency 337.IBAttributePlaceholdersKey 337.IBPluginDependency + 337.IBViewBoundsToFrameTransform 338.IBPluginDependency 34.CustomClassName 34.IBPluginDependency @@ -2749,6 +2793,7 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + PBIconAndTextCell com.apple.InterfaceBuilder.CocoaPlugin PBCollapsibleSplitView {{312, 577}, {852, 384}} @@ -2824,6 +2869,9 @@ com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABC6AAAwdAAAA + com.apple.InterfaceBuilder.CocoaPlugin GitXTextFieldCell com.apple.InterfaceBuilder.CocoaPlugin @@ -3060,6 +3108,13 @@ NSApplication+GitXScripting.h + + NSCell + + IBProjectSource + View/CellTrackingRect.h + + NSOutlineView @@ -3596,6 +3651,14 @@ PBHistorySearchController.h + + PBIconAndTextCell + NSTextFieldCell + + IBProjectSource + PBIconAndTextCell.h + + PBNiceSplitView NSSplitView @@ -4371,6 +4434,13 @@ QuartzCore.framework/Headers/CIImageProvider.h + + NSObject + + IBFrameworkSource + ScriptingBridge.framework/Headers/SBApplication.h + + NSObject diff --git a/PBGitIndexController.m b/PBGitIndexController.m index d72e8bc..02a5fce 100644 --- a/PBGitIndexController.m +++ b/PBGitIndexController.m @@ -113,6 +113,19 @@ [ignoreItem setTarget:self]; [ignoreItem setRepresentedObject:selectedFiles]; [menu addItem:ignoreItem]; + + if ([selectedFiles count] == 1) { + NSString *path = [[selectedFiles objectAtIndex:0] path]; + NSString *extension = [path pathExtension]; + if ([extension length] > 0) { + ignoreText = [NSString stringWithFormat:@"Ignore Files with extension (.%@)", extension]; + ignoreItem = [[NSMenuItem alloc] initWithTitle:ignoreText action:@selector(ignoreFilesWithExtensionAction:) keyEquivalent:@""]; + [ignoreItem setTarget:self]; + [ignoreItem setRepresentedObject:extension]; + [menu addItem:ignoreItem]; + [ignoreItem release]; + } + } } if ([selectedFiles count] == 1) { @@ -171,6 +184,18 @@ [commitController.index refresh]; } +- (void) ignoreFilesWithExtensionAction:(id) sender { + NSString *extension = [sender representedObject]; + if ([extension length] == 0) + return; + PBChangedFile *file = [[PBChangedFile alloc] initWithPath:[NSString stringWithFormat:@"*.%@", extension]]; + + + [self ignoreFiles:[NSArray arrayWithObject:file]]; + [file release]; + [commitController.index refresh]; +} + - (void)discardFilesAction:(id) sender { NSArray *selectedFiles = [sender representedObject]; @@ -226,7 +251,13 @@ - (void)tableView:(NSTableView*)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)rowIndex { id controller = [tableView tag] == 0 ? unstagedFilesController : stagedFilesController; - [[tableColumn dataCell] setImage:[[[controller arrangedObjects] objectAtIndex:rowIndex] icon]]; + PBChangedFile *changedFile = [[controller arrangedObjects] objectAtIndex:rowIndex]; + PBChangedFileStatus status = [changedFile status]; + NSImage *imageToSet = [changedFile icon]; + if (controller == stagedFilesController && status == NEW) { + imageToSet = [PBChangedFile iconForStatus:ADDED]; + } + [[tableColumn dataCell] setImage:imageToSet]; } - (void) tableClicked:(NSTableView *) tableView diff --git a/PBGitMenuItem.h b/PBGitMenuItem.h new file mode 100644 index 0000000..7e81edd --- /dev/null +++ b/PBGitMenuItem.h @@ -0,0 +1,20 @@ +// +// PBGitSVStashItem.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-05. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBSourceViewItem.h" +#import "PBPresentable.h" + + +@interface PBGitMenuItem : PBSourceViewItem { + id sourceObject; +} +@property (nonatomic, retain, readonly) id sourceObject; + +- initWithSourceObject:(id) anObject; +@end diff --git a/PBGitMenuItem.m b/PBGitMenuItem.m new file mode 100644 index 0000000..38b6895 --- /dev/null +++ b/PBGitMenuItem.m @@ -0,0 +1,62 @@ +// +// PBGitSVStashItem.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-05. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBGitMenuItem.h" + + +@implementation PBGitMenuItem +@synthesize sourceObject; + +#pragma mark - +#pragma mark Inits/dealloc +//--------------------------------------------------------------------------------------------- + +- initWithSourceObject:(id) anObject { + if (self = [super init]) { + super.title = [anObject displayDescription]; + sourceObject = [anObject retain]; + } + return self; +} + +- (void) dealloc { + [sourceObject release]; + [super dealloc]; +} + +//--------------------------------------------------------------------------------------------- +#pragma mark - + + +- (NSImage *) icon { + return [self.sourceObject icon]; +} + + +- (void) addChild:(PBGitMenuItem *)child { + BOOL added = NO; + for (PBGitMenuItem *item in self.children) { + if ([[(id)child.sourceObject path] hasPrefix:[(id)[item sourceObject] path]]) { + [item addChild:child]; + added = YES; + } + } + if (!added) { + [super addChild:child]; + } +} + +- (void) expand { + NSObject *item = self.parent; + while (item && [item isKindOfClass:[PBGitMenuItem class]]) { + [(id)item expand]; + item = [(id)item parent]; + } +} + +@end diff --git a/PBGitRepository.h b/PBGitRepository.h index 9c61a60..63fb753 100644 --- a/PBGitRepository.h +++ b/PBGitRepository.h @@ -12,6 +12,10 @@ #import "PBGitConfig.h" #import "PBGitRefish.h" +#import "PBStashController.h" +#import "PBGitResetController.h" +#import "PBSubmoduleController.h" + extern NSString* PBGitRepositoryErrorDomain; typedef enum branchFilterTypes { kGitXAllBranchesFilter = 0, @@ -52,7 +56,14 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { PBGitRevSpecifier *_headRef; // Caching PBGitSHA* _headSha; + + PBStashController *stashController; + PBSubmoduleController *submoduleController; + PBGitResetController *resetController; } +@property (nonatomic, retain, readonly) PBStashController *stashController; +@property (nonatomic, retain, readonly) PBSubmoduleController *submoduleController; +@property (nonatomic, retain, readonly) PBGitResetController *resetController; - (void) cloneRepositoryToPath:(NSString *)path bare:(BOOL)isBare; - (void) beginAddRemote:(NSString *)remoteName forURL:(NSString *)remoteURL; @@ -69,6 +80,12 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { - (BOOL) deleteRemote:(PBGitRef *)ref; - (BOOL) deleteRef:(PBGitRef *)ref; +- (BOOL) hasSvnRemote; +- (NSArray*) svnRemotes; +- (BOOL) svnFetch:(NSString*)remoteName; +- (BOOL) svnRebase:(NSString*)remoteName; +- (BOOL) svnDcommit:(NSString*)commitURL; + - (NSFileHandle*) handleForCommand:(NSString*) cmd; - (NSFileHandle*) handleForArguments:(NSArray*) args; - (NSFileHandle *) handleInWorkDirForArguments:(NSArray *)args; @@ -129,9 +146,9 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { - (void)findInModeScriptCommand:(NSScriptCommand *)command; -(NSNumber *)countCommintsOf:(NSString *)branchs; +- (NSMenu *) menu; +(bool)isLocalBranch:(NSString *)branch branchNameInto:(NSString **)name; - @property (assign) BOOL hasChanged; @property (readonly) PBGitWindowController *windowController; @property (readonly) PBGitConfig *config; diff --git a/PBGitRepository.m b/PBGitRepository.m index 34f10f3..50be481 100644 --- a/PBGitRepository.m +++ b/PBGitRepository.m @@ -21,13 +21,40 @@ #import "GitXScriptingConstants.h" #import "PBHistorySearchController.h" +#import "PBGitStash.h" +#import "PBGitSubmodule.h" + NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; -@implementation PBGitRepository +@interface PBGitRepository() +@end + + +@implementation PBGitRepository +@synthesize stashController; +@synthesize submoduleController; +@synthesize resetController; @synthesize revisionList, branches, currentBranch, refs, hasChanged, config; @synthesize currentBranchFilter; +- (NSMenu *) menu { + NSMenu *menu = [[NSMenu alloc] init]; + NSMutableArray *items = [[NSMutableArray alloc] init]; + [items addObjectsFromArray:[self.submoduleController menuItems]]; + [items addObject:[NSMenuItem separatorItem]]; + [items addObjectsFromArray:[self.stashController menu]]; + [items addObject:[NSMenuItem separatorItem]]; + [items addObjectsFromArray:[self.resetController menuItems]]; + + for (NSMenuItem *item in items) { + [menu addItem:item]; + } + + [menu setAutoenablesItems:YES]; + return menu; +} + - (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError { if (outError) { @@ -135,6 +162,10 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; [self reloadRefs]; currentBranchFilter = [PBGitDefaults branchFilter]; revisionList = [[PBGitHistoryList alloc] initWithRepository:self]; + + resetController = [[PBGitResetController alloc] initWithRepository:self]; + stashController = [[PBStashController alloc] initWithRepository:self]; + submoduleController = [[PBSubmoduleController alloc] initWithRepository:self]; } - (void)close @@ -280,6 +311,9 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; [self willChangeValueForKey:@"refs"]; [self didChangeValueForKey:@"refs"]; + + [self.stashController reload]; + [self.submoduleController reload]; [[[self windowController] window] setTitle:[self displayName]]; } @@ -895,6 +929,91 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; return YES; } +#pragma mark git svn commands + +/** + determines if the current repository has a git-svn configured remote + */ +- (BOOL) hasSvnRemote +{ + NSArray* remotes = [self svnRemotes]; + return remotes && [remotes count] > 0; +} + +/** + get a list of the svn remotes configured on this repository + */ +- (NSArray*) svnRemotes +{ + NSDictionary* configValues = [config listConfigValuesInDir:[self workingDirectory]]; + NSMutableArray* remotes = [NSMutableArray array]; + + for (NSString* key in configValues) { + NSArray* components = [key componentsSeparatedByString:@"."]; + if ([components count] == 3 && + [[components objectAtIndex:0] isEqualToString:@"svn-remote"] && + [[components objectAtIndex:2] isEqualToString:@"url"]) { + + NSString* remoteName = [components objectAtIndex:1]; + [remotes addObject:remoteName]; + } + } + return [NSArray arrayWithArray:remotes]; +} + +/** + call `git svn fetch` with an optional remote name + + remoteName can be NULL + */ +- (BOOL) svnFetch:(NSString*)remoteName +{ + int retval = 1; + NSArray* args = [NSArray arrayWithObjects:@"svn", @"fetch", remoteName, nil]; + + NSString *description = [NSString stringWithFormat:@"Fetching all tracking branches from %@", remoteName ? remoteName : @""]; + NSString *title = @"Fetching from svn remote"; + [PBRemoteProgressSheet beginRemoteProgressSheetForArguments:args title:title description:description inRepository:self]; + retval = 0; + + return retval == 0; +} + +/** + call `git svn rebase` with an optional remote name + + remoteName can be NULL + */ +- (BOOL) svnRebase:(NSString*)remoteName +{ + int retval = 1; + NSArray* args = [NSArray arrayWithObjects:@"svn", @"rebase", remoteName, nil]; + + NSString *description = [NSString stringWithFormat:@"Rebasing all tracking branches from %@", remoteName ? remoteName : @""]; + NSString *title = @"Pulling from svn remote (Rebase)"; + [PBRemoteProgressSheet beginRemoteProgressSheetForArguments:args title:title description:description inRepository:self]; + retval = 0; + + return retval == 0; +} + +/** + call `git svn dcommit` with optional commitURL + + commitURL can be NULL + */ +- (BOOL) svnDcommit:(NSString*)commitURL +{ + int retval = 1; + NSArray* args = [NSArray arrayWithObjects:@"svn", @"dcommit", commitURL, nil]; + + NSString *description = [NSString stringWithFormat:@"Pushing commits to svn remote %@", commitURL ? commitURL : @""]; + NSString *title = @"Pushing to svn remote (Dcommit)"; + [PBRemoteProgressSheet beginRemoteProgressSheetForArguments:args title:title description:description inRepository:self]; + retval = 0; + + return retval == 0; +} #pragma mark GitX Scripting @@ -1071,7 +1190,8 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; - (NSString*) outputInWorkdirForArguments:(NSArray*) arguments { - return [PBEasyPipe outputForCommand:[PBGitBinary path] withArgs:arguments inDir: [self workingDirectory]]; + NSString *output = [PBEasyPipe outputForCommand:[PBGitBinary path] withArgs:arguments inDir: [self workingDirectory]]; + return [output length] > 0 ? output : nil; } - (NSString*) outputInWorkdirForArguments:(NSArray *)arguments retValue:(int *)ret diff --git a/PBGitSidebarController.h b/PBGitSidebarController.h index 78d05ec..4126ff9 100644 --- a/PBGitSidebarController.h +++ b/PBGitSidebarController.h @@ -20,12 +20,16 @@ IBOutlet NSPopUpButton *actionButton; IBOutlet NSSegmentedControl *remoteControls; + IBOutlet NSButton* svnFetchButton; + IBOutlet NSButton* svnRebaseButton; + IBOutlet NSButton* svnDcommitButton; + NSMutableArray *items; /* Specific things */ PBSourceViewItem *stage; - PBSourceViewItem *branches, *remotes, *tags, *others; + PBSourceViewItem *branches, *remotes, *tags, *others, *stashes, *submodules; PBGitHistoryController *historyViewController; PBGitCommitController *commitViewController; @@ -37,6 +41,9 @@ - (NSMenu *) menuForRow:(NSInteger)row; - (IBAction) fetchPullPushAction:(id)sender; +- (IBAction) svnFetch:(id)sender; +- (IBAction) svnRebase:(id)sender; +- (IBAction) svnDcommit:(id)sender; - (void)setHistorySearch:(NSString *)searchString mode:(NSInteger)mode; diff --git a/PBGitSidebarController.m b/PBGitSidebarController.m index 48901ae..7be189d 100644 --- a/PBGitSidebarController.m +++ b/PBGitSidebarController.m @@ -16,6 +16,16 @@ #import "PBAddRemoteSheet.h" #import "PBGitDefaults.h" #import "PBHistorySearchController.h" +#import "PBGitMenuItem.h" + +#import "PBStashCommandFactory.h" +#import "PBRemoteCommandFactory.h" +#import "PBCommandMenuItem.h" +#import "PBGitStash.h" +#import "PBGitSubmodule.h" + +static NSString * const kObservingContextStashes = @"stashesChanged"; +static NSString * const kObservingContextSubmodules = @"submodulesChanged"; @interface PBGitSidebarController () @@ -38,7 +48,7 @@ self = [super initWithRepository:theRepository superController:controller]; [sourceView setDelegate:self]; items = [NSMutableArray array]; - + return self; } @@ -47,30 +57,38 @@ [super awakeFromNib]; window.contentView = self.view; [self populateList]; - + historyViewController = [[PBGitHistoryController alloc] initWithRepository:repository superController:superController]; commitViewController = [[PBGitCommitController alloc] initWithRepository:repository superController:superController]; - + [repository addObserver:self forKeyPath:@"refs" options:0 context:@"updateRefs"]; [repository addObserver:self forKeyPath:@"currentBranch" options:0 context:@"currentBranchChange"]; [repository addObserver:self forKeyPath:@"branches" options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew) context:@"branchesModified"]; - + [repository addObserver:self forKeyPath:@"stashController.stashes" options:NSKeyValueObservingOptionNew context:kObservingContextStashes]; + [repository addObserver:self forKeyPath:@"submoduleController.submodules" options:NSKeyValueObservingOptionNew context:kObservingContextSubmodules]; + + [self menuNeedsUpdate:[actionButton menu]]; - + if ([PBGitDefaults showStageView]) [self selectStage]; else [self selectCurrentBranch]; + + [sourceView setDoubleAction:@selector(outlineDoubleClicked)]; + [sourceView setTarget:self]; } - (void)closeView { [historyViewController closeView]; [commitViewController closeView]; - + [repository removeObserver:self forKeyPath:@"currentBranch"]; [repository removeObserver:self forKeyPath:@"branches"]; - + [repository removeObserver:self forKeyPath:@"stashController.stashes"]; + [repository removeObserver:self forKeyPath:@"submoduleController.submodules"]; + [super closeView]; } @@ -79,10 +97,9 @@ if ([@"currentBranchChange" isEqualToString:context]) { [sourceView reloadData]; [self selectCurrentBranch]; - return; }else if ([@"branchesModified" isEqualToString:context]) { NSInteger changeKind = [(NSNumber *)[change objectForKey:NSKeyValueChangeKindKey] intValue]; - + if (changeKind == NSKeyValueChangeInsertion) { NSArray *newRevSpecs = [change objectForKey:NSKeyValueChangeNewKey]; for (PBGitRevSpecifier *rev in newRevSpecs) { @@ -96,6 +113,41 @@ for (PBGitRevSpecifier *rev in removedRevSpecs) [self removeRevSpec:rev]; } + } else if ([kObservingContextStashes isEqualToString:context]) { // isEqualToString: is not needed here + [stashes.children removeAllObjects]; + NSArray *newStashes = [change objectForKey:NSKeyValueChangeNewKey]; + + PBGitMenuItem *lastItem = nil; + for (PBGitStash *stash in newStashes) { + PBGitMenuItem *item = [[PBGitMenuItem alloc] initWithSourceObject:stash]; + [stashes addChild:item]; + [item release]; + lastItem = item; + } + if (lastItem) { + [sourceView PBExpandItem:lastItem expandParents:YES]; + } + [sourceView reloadData]; + } else if ([kObservingContextSubmodules isEqualToString:context]) { + [submodules.children removeAllObjects]; + NSArray *newSubmodules = [change objectForKey:NSKeyValueChangeNewKey]; + + for (PBGitSubmodule *submodule in newSubmodules) { + PBGitMenuItem *item = [[PBGitMenuItem alloc] initWithSourceObject:submodule]; + + BOOL added = NO; + for (PBGitMenuItem *addedItems in [submodules children]) { + if ([[submodule path] hasPrefix:[(id)[addedItems sourceObject] path]]) { + [addedItems addChild:item]; + added = YES; + } + } + if (!added) { + [submodules addChild:item]; + } + [sourceView PBExpandItem:item expandParents:YES]; + } + [sourceView reloadData]; }else if ([@"updateRefs" isEqualToString:context]) { for(PBGitSVRemoteItem* remote in [remotes children]){ NSLog(@"remote.title=%@",[remote title]); @@ -143,7 +195,7 @@ { NSInteger index = [sourceView selectedRow]; PBSourceViewItem *item = [sourceView itemAtRow:index]; - + return item; } @@ -182,6 +234,17 @@ [sourceView selectRowIndexes:index byExtendingSelection:NO]; } +- (void) outlineDoubleClicked { + PBSourceViewItem *item = [self selectedItem]; + if ([item isKindOfClass:[PBGitMenuItem class]]) { + PBGitMenuItem *sidebarItem = (PBGitMenuItem *) item; + NSObject *sourceObject = [sidebarItem sourceObject]; + if ([sourceObject isKindOfClass:[PBGitSubmodule class]]) { + [[repository.submoduleController defaultCommandForSubmodule:(id)sourceObject] invoke]; + } + } +} + - (PBSourceViewItem *) itemForRev:(PBGitRevSpecifier *)rev { PBSourceViewItem *foundItem = nil; @@ -198,7 +261,7 @@ [sourceView reloadData]; return; } - + NSArray *pathComponents = [[rev simpleRef] componentsSeparatedByString:@"/"]; if ([pathComponents count] < 2) [branches addChild:[PBSourceViewItem itemWithRevSpec:rev]]; @@ -208,16 +271,17 @@ [tags addRev:rev toPath:[pathComponents subarrayWithRange:NSMakeRange(2, [pathComponents count] - 2)]]; else if ([[rev simpleRef] hasPrefix:@"refs/remotes/"]) [remotes addRev:rev toPath:[pathComponents subarrayWithRange:NSMakeRange(2, [pathComponents count] - 2)]]; + [sourceView reloadData]; } - (void) removeRevSpec:(PBGitRevSpecifier *)rev { PBSourceViewItem *item = [self itemForRev:rev]; - + if (!item) return; - + PBSourceViewItem *parent = item.parent; [parent removeChild:item]; [sourceView reloadData]; @@ -234,19 +298,19 @@ { NSInteger index = [sourceView selectedRow]; PBSourceViewItem *item = [sourceView itemAtRow:index]; - + if ([item revSpecifier]) { if (![repository.currentBranch isEqual:[item revSpecifier]]) repository.currentBranch = [item revSpecifier]; [superController changeContentController:historyViewController]; [PBGitDefaults setShowStageView:NO]; } - + if (item == stage) { [superController changeContentController:commitViewController]; [PBGitDefaults setShowStageView:YES]; } - + [self updateActionMenu]; [self updateRemoteControls]; } @@ -259,6 +323,14 @@ - (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(PBSourceViewCell *)cell forTableColumn:(NSTableColumn *)tableColumn item:(PBSourceViewItem *)item { + BOOL showsActionButton = NO; + if ([item respondsToSelector:@selector(showsActionButton)]) { + showsActionButton = [item showsActionButton]; + [cell setTarget:self]; + cell.iInfoButtonAction = @selector(infoButtonAction:); + } + cell.showsActionButton = showsActionButton; + [cell setBadge:[item badge]]; [cell setImage:[item icon]]; } @@ -268,6 +340,10 @@ return ![item isGroupItem]; } +- (BOOL)outlineView:(NSOutlineView *)outlineView shouldTrackCell:(NSCell *)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item { + return [item isGroupItem]; +} + // // The next method is necessary to hide the triangle for uncollapsible items // That is, items which should always be displayed, such as the Project group. @@ -280,30 +356,37 @@ - (void)populateList { PBSourceViewItem *project = [PBSourceViewItem groupItemWithTitle:[repository projectName]]; + project.showsActionButton = YES; project.isUncollapsible = YES; - + stage = [PBGitSVStageItem stageItem]; [project addChild:stage]; + branches = [PBSourceViewItem groupItemWithTitle:@"Branches"]; remotes = [PBSourceViewItem groupItemWithTitle:@"Remotes"]; tags = [PBSourceViewItem groupItemWithTitle:@"Tags"]; others = [PBSourceViewItem groupItemWithTitle:@"Other"]; - + stashes = [PBSourceViewItem groupItemWithTitle:@"Stashes"]; + submodules = [PBSourceViewItem groupItemWithTitle:@"Submodules"]; + for (PBGitRevSpecifier *rev in repository.branches) [self addRevSpec:rev]; - + [items addObject:project]; [items addObject:branches]; [items addObject:remotes]; [items addObject:tags]; [items addObject:others]; - + [items addObject:stashes]; + [items addObject:submodules]; + [sourceView reloadData]; [sourceView expandItem:project]; [sourceView expandItem:branches expandChildren:YES]; [sourceView expandItem:remotes]; - + //[sourceView expandItem:submodules expandChildren:YES]; + [sourceView reloadItem:nil reloadChildren:YES]; } @@ -313,7 +396,7 @@ { if (!item) return [items objectAtIndex:index]; - + return [[(PBSourceViewItem *)item children] objectAtIndex:index]; } @@ -326,7 +409,7 @@ { if (!item) return [items count]; - + return [[(PBSourceViewItem *)item children] count]; } @@ -347,7 +430,7 @@ { if (!ref) return; - + for (NSMenuItem *menuItem in [historyViewController.refController menuItemsForRef:ref]) [menu addItem:menuItem]; } @@ -358,22 +441,42 @@ NSImage *actionIcon = [NSImage imageNamed:@"NSActionTemplate"]; [actionIcon setSize:NSMakeSize(12, 12)]; [actionIconItem setImage:actionIcon]; - + return actionIconItem; } - (NSMenu *) menuForRow:(NSInteger)row { + if (row == 0) { + return [historyViewController.repository menu]; + } PBSourceViewItem *viewItem = [sourceView itemAtRow:row]; - + if ([viewItem isKindOfClass:[PBGitMenuItem class]]) { + PBGitMenuItem *stashItem = (PBGitMenuItem *) viewItem; + NSMutableArray *commands = [[NSMutableArray alloc] init]; + [commands addObjectsFromArray:[PBStashCommandFactory commandsForObject:[stashItem sourceObject] repository:historyViewController.repository]]; + [commands addObjectsFromArray:[PBRemoteCommandFactory commandsForObject:[stashItem sourceObject] repository:historyViewController.repository]]; + if (!commands) { + return nil; + } + NSMenu *menu = [[NSMenu alloc] init]; + [menu setAutoenablesItems:NO]; + for (PBCommand *command in commands) { + PBCommandMenuItem *item = [[PBCommandMenuItem alloc] initWithCommand:command]; + [menu addItem:item]; + [item release]; + } + return menu; + } + PBGitRef *ref = [viewItem ref]; if (!ref) return nil; - + NSMenu *menu = [[NSMenu alloc] init]; [menu setAutoenablesItems:NO]; [self addMenuItemsForRef:ref toMenu:menu]; - + return menu; } @@ -382,7 +485,7 @@ { [actionButton removeAllItems]; [menu addItem:[self actionIconItem]]; - + PBGitRef *ref = [[self selectedItem] ref]; [self addMenuItemsForRef:ref toMenu:menu]; } @@ -400,39 +503,45 @@ enum { - (void) updateRemoteControls { BOOL hasRemote = NO; - + PBGitRef *ref = [[self selectedItem] ref]; if ([ref isRemote] || ([ref isBranch] && [[repository remoteRefForBranch:ref error:NULL] remoteName])) hasRemote = YES; - + [remoteControls setEnabled:hasRemote forSegment:kFetchSegment]; [remoteControls setEnabled:hasRemote forSegment:kPullSegment]; [remoteControls setEnabled:hasRemote forSegment:kPushSegment]; + + // get config + BOOL hasSVN = [repository hasSvnRemote]; + [svnFetchButton setEnabled:hasSVN]; + [svnRebaseButton setEnabled:hasSVN]; + [svnDcommitButton setEnabled:hasSVN]; } - (IBAction) fetchPullPushAction:(id)sender { NSInteger selectedSegment = [sender selectedSegment]; - + if (selectedSegment == kAddRemoteSegment) { [PBAddRemoteSheet beginAddRemoteSheetForRepository:repository]; return; } - + NSInteger index = [sourceView selectedRow]; PBSourceViewItem *item = [sourceView itemAtRow:index]; PBGitRef *ref = [[item revSpecifier] ref]; - + if (!ref && (item.parent == remotes)) ref = [PBGitRef refFromString:[kGitXRemoteRefPrefix stringByAppendingString:[item title]]]; - + if (![ref isRemote] && ![ref isBranch]) return; - + PBGitRef *remoteRef = [repository remoteRefForBranch:ref error:NULL]; if (!remoteRef) return; - + if (selectedSegment == kFetchSegment) [repository beginFetchFromRemoteForRef:ref]; else if (selectedSegment == kPullSegment) @@ -445,5 +554,21 @@ enum { } } +- (IBAction) svnFetch:(id)sender +{ + [repository svnFetch:nil]; +} + +- (IBAction) svnRebase:(id)sender +{ + printf("git svn rebase"); + [repository svnRebase:nil]; +} + +- (IBAction) svnDcommit:(id)sender +{ + printf("git svn dcommit"); + [repository svnDcommit:nil]; +} @end diff --git a/PBGitSidebarView.xib b/PBGitSidebarView.xib index cdf65f9..bf1d2d4 100644 --- a/PBGitSidebarView.xib +++ b/PBGitSidebarView.xib @@ -2,18 +2,29 @@ 1050 - 10C540 - 759 - 1038.25 - 458.00 + 10F569 + 1222 + 1038.29 + 461.00 com.apple.InterfaceBuilder.CocoaPlugin - 759 + 804 YES - - + NSSegmentedControl + NSPopUpButton + NSScroller + NSMenuItem + NSMenu + NSTextFieldCell + NSScrollView + NSOutlineView + NSCustomView + NSCustomObject + NSPopUpButtonCell + NSTableColumn + NSSegmentedCell YES @@ -59,6 +70,8 @@ 4352 {153, 354} + + YES @@ -78,7 +91,7 @@ LucidaGrande 11 - 3100 + 3088 3 @@ -161,6 +174,7 @@ {153, 354} + @@ -171,6 +185,8 @@ -2147483392 {{137, 1}, {15, 338}} + + _doScroller: 0.99698790000000004 @@ -180,6 +196,8 @@ -2147483392 {{-100, -100}, {196, 15}} + + 1 _doScroller: @@ -188,7 +206,8 @@ {153, 354} - + + 528 @@ -198,13 +217,79 @@ {153, 354} + + NSView - + 268 YES + + + 268 + {{201, 2}, {92, 25}} + + YES + + -2080244224 + 134217728 + SVN fetch + + LucidaGrande + 13 + 1044 + + + -2033434369 + 163 + + + 400 + 75 + + + + + 268 + {{398, 2}, {107, 25}} + + YES + + -2080244224 + 134217728 + SVN dcommit + + + -2033434369 + 163 + + + 400 + 75 + + + + + 268 + {{301, 2}, {92, 25}} + + YES + + -2080244224 + 134217728 + SVN rebase + + + -2033434369 + 163 + + + 400 + 75 + + 268 @@ -278,11 +363,7 @@ -2076049856 134219776 - - LucidaGrande - 13 - 1044 - + -2034220801 163 @@ -353,13 +434,13 @@ - {200, 31} + {515, 31} NSView - + YES @@ -433,6 +514,54 @@ 51 + + + svnFetchButton + + + + 58 + + + + svnRebaseButton + + + + 59 + + + + svnDcommitButton + + + + 60 + + + + svnFetch: + + + + 61 + + + + svnRebase: + + + + 62 + + + + svnDcommit: + + + + 63 + @@ -522,6 +651,9 @@ YES + + + Source List Controls View @@ -584,6 +716,48 @@ + + 52 + + + YES + + + + + + 53 + + + YES + + + + + + 54 + + + YES + + + + + + 55 + + + + + 56 + + + + + 57 + + + @@ -592,6 +766,7 @@ YES -3.IBPluginDependency 10.IBPluginDependency + 11.CustomClassName 11.IBPluginDependency 13.IBPluginDependency 16.CustomClassName @@ -609,6 +784,18 @@ 47.IBPluginDependency 48.IBPluginDependency 48.IBSegmentedControlInspectorSelectedSegmentMetadataKey + 52.IBAttributePlaceholdersKey + 52.IBPluginDependency + 52.IBViewBoundsToFrameTransform + 53.IBAttributePlaceholdersKey + 53.IBPluginDependency + 53.IBViewBoundsToFrameTransform + 54.IBAttributePlaceholdersKey + 54.IBPluginDependency + 54.IBViewBoundsToFrameTransform + 55.IBPluginDependency + 56.IBPluginDependency + 57.IBPluginDependency 8.IBEditorWindowLastContentRect 8.IBPluginDependency 9.IBPluginDependency @@ -617,13 +804,14 @@ YES com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + TrackableOutlineView com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin PBSourceViewCell com.apple.InterfaceBuilder.CocoaPlugin - {{482, 590}, {153, 354}} + {{482, 502}, {153, 354}} com.apple.InterfaceBuilder.CocoaPlugin - {{626, 507}, {200, 31}} + {{374, 430}, {515, 31}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -634,6 +822,45 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Merge + + + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABCQAAAwcgAAA + + + ToolTip + + ToolTip + + Merge + + + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDEQAAwcgAAA + + + ToolTip + + ToolTip + + Merge + + + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAADCUAAAwcgAAA + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin {{105, 545}, {153, 354}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -655,11 +882,18 @@ - 51 + 63 YES + + NSApplication + + IBProjectSource + NSApplication+GitXScripting.h + + NSOutlineView @@ -671,8 +905,50 @@ PBGitSidebarController PBViewController - fetchPullPushAction: - id + YES + + YES + fetchPullPushAction: + svnDcommit: + svnFetch: + svnRebase: + + + YES + id + id + id + id + + + + YES + + YES + fetchPullPushAction: + svnDcommit: + svnFetch: + svnRebase: + + + YES + + fetchPullPushAction: + id + + + svnDcommit: + id + + + svnFetch: + id + + + svnRebase: + id + + YES @@ -682,6 +958,9 @@ remoteControls sourceListControlsView sourceView + svnDcommitButton + svnFetchButton + svnRebaseButton window @@ -690,12 +969,64 @@ NSSegmentedControl NSView NSOutlineView + NSButton + NSButton + NSButton NSWindow + + YES + + YES + actionButton + remoteControls + sourceListControlsView + sourceView + svnDcommitButton + svnFetchButton + svnRebaseButton + window + + + YES + + actionButton + NSPopUpButton + + + remoteControls + NSSegmentedControl + + + sourceListControlsView + NSView + + + sourceView + NSOutlineView + + + svnDcommitButton + NSButton + + + svnFetchButton + NSButton + + + svnRebaseButton + NSButton + + + window + NSWindow + + + IBProjectSource - PBGitSidebarController.h + ./classes-xjh84/PBGitSidebarController.h @@ -703,7 +1034,7 @@ NSTextFieldCell IBProjectSource - PBIconAndTextCell.h + ./classes-xjh84/PBIconAndTextCell.h @@ -711,12 +1042,23 @@ PBIconAndTextCell IBProjectSource - PBSourceViewCell.h + ./classes-xjh84/PBSourceViewCell.h PBViewController NSViewController + + refresh: + id + + + refresh: + + refresh: + id + + IBProjectSource PBViewController.h @@ -1084,6 +1426,34 @@ Foundation.framework/Headers/NSURLDownload.h + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CAAnimation.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CALayer.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CIImageProvider.h + + + + NSObject + + IBFrameworkSource + ScriptingBridge.framework/Headers/SBApplication.h + + NSObject @@ -1287,6 +1657,13 @@ view NSView + + view + + view + NSView + + IBFrameworkSource AppKit.framework/Headers/NSViewController.h @@ -1298,35 +1675,32 @@ IBFrameworkSource AppKit.framework/Headers/NSDrawer.h - - - NSWindow - NSResponder - IBFrameworkSource - AppKit.framework/Headers/NSWindow.h + IBProjectSource + ./classes-xjh84/PBViewController.h - NSWindow + TrackableOutlineView + NSOutlineView - IBFrameworkSource - AppKit.framework/Headers/NSWindowScripting.h + IBProjectSource + ./classes-xjh84/TrackableOutlineView.h 0 IBCocoaFramework - + com.apple.InterfaceBuilder.CocoaPlugin.macosx - + com.apple.InterfaceBuilder.CocoaPlugin.macosx - + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 @@ -1334,8 +1708,27 @@ GitX.xcodeproj 3 - NSActionTemplate - {15, 15} + YES + + YES + AddRemote + FetchTemplate + NSActionTemplate + NSMenuCheckmark + NSMenuMixedState + PullTemplate + PushTemplate + + + YES + {23, 12} + {16.4571, 12.3429} + {15, 15} + {9, 8} + {7, 2} + {16.4571, 12.3429} + {16.4571, 12.3429} + diff --git a/PBGitTree.m b/PBGitTree.m index 2f7af52..c966fa5 100644 --- a/PBGitTree.m +++ b/PBGitTree.m @@ -131,7 +131,9 @@ if(error==nil){ res=[repository outputInWorkdirForArguments:[NSArray arrayWithObjects:@"blame", @"-p", sha, @"--", [self fullPath], nil]]; }else{ - *anError = [NSError errorWithDomain:@"blame" code:1 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:error,NSLocalizedDescriptionKey,nil]]; + if (anError != NULL) { + *anError = [NSError errorWithDomain:@"blame" code:1 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:error,NSLocalizedDescriptionKey,nil]]; + } } return res; @@ -147,7 +149,9 @@ if(error==nil){ res=[repository outputInWorkdirForArguments:[NSArray arrayWithObjects:@"log", [NSString stringWithFormat:@"--pretty=format:%@",format], @"--", [self fullPath], nil]]; }else{ - *anError = [NSError errorWithDomain:@"log" code:1 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:error,NSLocalizedDescriptionKey,nil]]; + if (anError != NULL) { + *anError = [NSError errorWithDomain:@"log" code:1 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:error,NSLocalizedDescriptionKey,nil]]; + } } return res; @@ -178,12 +182,16 @@ res=[repository outputInWorkdirForArguments:[NSArray arrayWithObjects:@"diff", sha, des,[self fullPath], nil]]; if ([res length]==0) { NSLog(@"--%d",[res length]); - *anError = [NSError errorWithDomain:@"diff" code:1 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"No Diff",NSLocalizedDescriptionKey,nil]]; + if (anError != NULL) { + *anError = [NSError errorWithDomain:@"diff" code:1 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"No Diff",NSLocalizedDescriptionKey,nil]]; + } }else{ NSLog(@"--%@",[res substringToIndex:80]); } }else{ - *anError = [NSError errorWithDomain:@"diff" code:1 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:error,NSLocalizedDescriptionKey,nil]]; + if (anError != NULL) { + *anError = [NSError errorWithDomain:@"diff" code:1 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:error,NSLocalizedDescriptionKey,nil]]; + } } return res; @@ -205,7 +213,9 @@ if(error==nil){ res = [self contents]; }else{ - *anError = [NSError errorWithDomain:@"show" code:1 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:error,NSLocalizedDescriptionKey,nil]]; + if (anError != NULL) { + *anError = [NSError errorWithDomain:@"show" code:1 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:error,NSLocalizedDescriptionKey,nil]]; + } } return res; diff --git a/PBGitWindowController.h b/PBGitWindowController.h index 0f38e22..9b008fc 100644 --- a/PBGitWindowController.h +++ b/PBGitWindowController.h @@ -25,8 +25,6 @@ IBOutlet NSTextField *statusField; IBOutlet NSProgressIndicator *progressIndicator; - PBViewController* viewController; - IBOutlet NSToolbarItem *terminalItem; IBOutlet NSToolbarItem *finderItem; } diff --git a/PBGitWindowController.m b/PBGitWindowController.m index ba926be..b08dfc2 100644 --- a/PBGitWindowController.m +++ b/PBGitWindowController.m @@ -9,6 +9,7 @@ #import "PBGitWindowController.h" #import "PBGitHistoryController.h" #import "PBGitCommitController.h" +#import "PBGitDefaults.h" #import "Terminal.h" #import "PBCloneRepsitoryToSheet.h" #import "PBCommitHookFailedSheet.h" @@ -132,6 +133,14 @@ [[NSAlert alertWithError:error] beginSheetModalForWindow:[self window] modalDelegate:self didEndSelector:nil contextInfo:nil]; } + +- (void)windowDidBecomeKey:(NSNotification *)notification +{ + if ([PBGitDefaults refreshAutomatically]) { + [contentController refresh:nil]; + } +} + - (void)showErrorSheetTitle:(NSString *)title message:(NSString *)message arguments:(NSArray *)arguments output:(NSString *)output { NSString *command = [arguments componentsJoinedByString:@" "]; diff --git a/PBIconAndTextCell.m b/PBIconAndTextCell.m index c2c0052..210b23d 100644 --- a/PBIconAndTextCell.m +++ b/PBIconAndTextCell.m @@ -26,12 +26,12 @@ return cell; } -- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(NSInteger)selStart length:(NSInteger)selLength -{ - NSRect textFrame, imageFrame; - NSDivideRect (aRect, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge); - [super selectWithFrame: textFrame inView: controlView editor:textObj delegate:anObject start:selStart length:selLength]; -} +//- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(NSInteger)selStart length:(NSInteger)selLength +//{ +// NSRect textFrame, imageFrame; +// NSDivideRect (aRect, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge); +// [super selectWithFrame: textFrame inView: controlView editor:textObj delegate:anObject start:selStart length:selLength]; +//} - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { @@ -69,56 +69,56 @@ // = Hit testing = // =============== // Adopted from PhotoSearch Apple sample code +// +//- (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView +//{ +// NSPoint point = [controlView convertPoint:[event locationInWindow] fromView:nil]; +// +// NSRect textFrame, imageFrame; +// NSDivideRect (cellFrame, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge); +// if (NSMouseInRect(point, imageFrame, [controlView isFlipped])) +// return NSCellHitContentArea | NSCellHitTrackableArea; +// +// return [super hitTestForEvent:event inRect:cellFrame ofView:controlView]; +//} -- (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView -{ - NSPoint point = [controlView convertPoint:[event locationInWindow] fromView:nil]; - - NSRect textFrame, imageFrame; - NSDivideRect (cellFrame, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge); - if (NSMouseInRect(point, imageFrame, [controlView isFlipped])) - return NSCellHitContentArea | NSCellHitTrackableArea; - - return [super hitTestForEvent:event inRect:cellFrame ofView:controlView]; -} - -+ (BOOL)prefersTrackingUntilMouseUp -{ - // NSCell returns NO for this by default. If you want to have trackMouse:inRect:ofView:untilMouseUp: always track until the mouse is up, then you MUST return YES. Otherwise, strange things will happen. - return YES; -} - -- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)flag -{ - [self setControlView:controlView]; - - NSRect textFrame, imageFrame; - NSDivideRect (cellFrame, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge); - while ([theEvent type] != NSLeftMouseUp) { - // This is VERY simple event tracking. We simply check to see if the mouse is in the "i" button or not and dispatch entered/exited mouse events - NSPoint point = [controlView convertPoint:[theEvent locationInWindow] fromView:nil]; - BOOL mouseInButton = NSMouseInRect(point, imageFrame, [controlView isFlipped]); - if (mouseDownInButton != mouseInButton) { - mouseDownInButton = mouseInButton; - [controlView setNeedsDisplayInRect:cellFrame]; - } - if ([theEvent type] == NSMouseEntered || [theEvent type] == NSMouseExited) - [NSApp sendEvent:theEvent]; - // Note that we process mouse entered and exited events and dispatch them to properly handle updates - theEvent = [[controlView window] nextEventMatchingMask:(NSLeftMouseUpMask | NSLeftMouseDraggedMask | NSMouseEnteredMask | NSMouseExitedMask)]; - } - - // Another way of implementing the above code would be to keep an NSButtonCell as an ivar, and simply call trackMouse:inRect:ofView:untilMouseUp: on it, if the tracking area was inside of it. - if (mouseDownInButton) { - // Send the action, and redisplay - mouseDownInButton = NO; - [controlView setNeedsDisplayInRect:cellFrame]; - if (self.action) - [NSApp sendAction:self.action to:self.target from:self]; - } - - // We return YES since the mouse was released while we were tracking. Not returning YES when you processed the mouse up is an easy way to introduce bugs! - return YES; -} +//+ (BOOL)prefersTrackingUntilMouseUp +//{ +// // NSCell returns NO for this by default. If you want to have trackMouse:inRect:ofView:untilMouseUp: always track until the mouse is up, then you MUST return YES. Otherwise, strange things will happen. +// return YES; +//} +// +//- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)flag +//{ +// [self setControlView:controlView]; +// +// NSRect textFrame, imageFrame; +// NSDivideRect (cellFrame, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge); +// while ([theEvent type] != NSLeftMouseUp) { +// // This is VERY simple event tracking. We simply check to see if the mouse is in the "i" button or not and dispatch entered/exited mouse events +// NSPoint point = [controlView convertPoint:[theEvent locationInWindow] fromView:nil]; +// BOOL mouseInButton = NSMouseInRect(point, imageFrame, [controlView isFlipped]); +// if (mouseDownInButton != mouseInButton) { +// mouseDownInButton = mouseInButton; +// [controlView setNeedsDisplayInRect:cellFrame]; +// } +// if ([theEvent type] == NSMouseEntered || [theEvent type] == NSMouseExited) +// [NSApp sendEvent:theEvent]; +// // Note that we process mouse entered and exited events and dispatch them to properly handle updates +// theEvent = [[controlView window] nextEventMatchingMask:(NSLeftMouseUpMask | NSLeftMouseDraggedMask | NSMouseEnteredMask | NSMouseExitedMask)]; +// } +// +// // Another way of implementing the above code would be to keep an NSButtonCell as an ivar, and simply call trackMouse:inRect:ofView:untilMouseUp: on it, if the tracking area was inside of it. +// if (mouseDownInButton) { +// // Send the action, and redisplay +// mouseDownInButton = NO; +// [controlView setNeedsDisplayInRect:cellFrame]; +// if (self.action) +// [NSApp sendAction:self.action to:self.target from:self]; +// } +// +// // We return YES since the mouse was released while we were tracking. Not returning YES when you processed the mouse up is an easy way to introduce bugs! +// return YES; +//} @end diff --git a/PBRefController.m b/PBRefController.m index 47eda03..2ca8941 100644 --- a/PBRefController.m +++ b/PBRefController.m @@ -14,6 +14,7 @@ #import "PBGitDefaults.h" #import "PBDiffWindowController.h" +#import "PBArgumentPickerController.h" #define kDialogAcceptDroppedRef @"Accept Dropped Ref" #define kDialogConfirmPush @"Confirm Push" @@ -228,7 +229,7 @@ } - (void) showTagInfoSheet:(PBRefMenuItem *)sender -{ +{ if ([[sender refish] refishType] != kGitXTagType) return; diff --git a/PBRefMenuItem.m b/PBRefMenuItem.m index 083de7b..aaaee1f 100644 --- a/PBRefMenuItem.m +++ b/PBRefMenuItem.m @@ -8,6 +8,9 @@ #import "PBRefMenuItem.h" +#import "PBStashCommandFactory.h" +#import "PBCommandMenuItem.h" + @implementation PBRefMenuItem @synthesize refish; @@ -133,7 +136,7 @@ [items addObject:[PBRefMenuItem separatorItem]]; NSString *deleteTitle = [NSString stringWithFormat:@"Delete %@…", targetRefName]; [items addObject:[PBRefMenuItem itemWithTitle:deleteTitle action:@selector(showDeleteRefSheet:) enabled:!isDetachedHead]]; - + for (PBRefMenuItem *item in items) { [item setTarget:target]; [item setRefish:ref]; diff --git a/PBSourceViewCell.h b/PBSourceViewCell.h index fc04a3e..56c4ccf 100644 --- a/PBSourceViewCell.h +++ b/PBSourceViewCell.h @@ -11,8 +11,14 @@ @interface PBSourceViewCell : PBIconAndTextCell { NSString *badge; + BOOL showsActionButton; + + BOOL iMouseDownInInfoButton; + BOOL iMouseHoveredInInfoButton; + SEL iInfoButtonAction; } - +@property (nonatomic) BOOL showsActionButton; +@property (nonatomic) SEL iInfoButtonAction; @property (assign) NSString *badge; @end diff --git a/PBSourceViewCell.m b/PBSourceViewCell.m index ed89668..06221d8 100644 --- a/PBSourceViewCell.m +++ b/PBSourceViewCell.m @@ -10,18 +10,27 @@ #import "PBGitSidebarController.h" #import "PBSourceViewBadge.h" - - +@interface PBSourceViewCell() +- (NSRect)infoButtonRectForBounds:(NSRect)bounds; +@end @implementation PBSourceViewCell - +@synthesize iInfoButtonAction; +@synthesize showsActionButton; @synthesize badge; # pragma mark context menu delegate methods +- init { + if (self = [super init]) { + + } + return self; +} + - (NSMenu *) menuForEvent:(NSEvent *)event inRect:(NSRect)rect ofView:(NSOutlineView *)view { - NSPoint point = [view convertPoint:[event locationInWindow] fromView:nil]; + NSPoint point = [self.controlView convertPoint:[event locationInWindow] fromView:nil]; NSInteger row = [view rowAtPoint:point]; PBGitSidebarController *controller = [view delegate]; @@ -52,4 +61,152 @@ [super drawWithFrame:cellFrame inView:outlineView]; } + +#pragma mark - +#pragma mark Button support + +- (NSRect)infoButtonRectForBounds:(NSRect)bounds { + CGFloat infoButtonWidth = 17.0f; + CGFloat infoButtonHeight = 11.0f; + return NSMakeRect(NSMaxX(bounds) - infoButtonWidth, NSMinY(bounds) + (NSHeight(bounds) - infoButtonHeight)/2.0f, infoButtonWidth, infoButtonHeight); +} + +- (NSImage *)infoButtonImage { + // Construct an image name based on our current state + NSString *imageName = [NSString stringWithFormat:@"sourceListAction%@.png", + //[self isHighlighted] ? @"selected" : @"normal", + iMouseDownInInfoButton ? @"Over" : + iMouseHoveredInInfoButton ? @"Over" : @""]; + return [NSImage imageNamed:imageName]; +} + +- (void)drawInteriorWithFrame:(NSRect)bounds inView:(NSView *)controlView { + [super drawInteriorWithFrame:bounds inView:controlView]; + + if (showsActionButton) { + NSRect infoButtonRect = [self infoButtonRectForBounds:bounds]; + NSImage *anImage = [self infoButtonImage]; + [anImage setFlipped:[controlView isFlipped]]; + [anImage drawInRect:infoButtonRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; + } +} + + +//- (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView { +// if (showsActionButton) { +// NSPoint point = [controlView convertPoint:[event locationInWindow] fromView:nil]; +// // +// // NSRect titleRect = [self titleRectForBounds:cellFrame]; +// // if (NSMouseInRect(point, titleRect, [controlView isFlipped])) { +// // return NSCellHitContentArea | NSCellHitEditableTextArea; +// // } +// // +// // NSRect imageRect = [self imageRectForBounds:cellFrame]; +// // if (NSMouseInRect(point, imageRect, [controlView isFlipped])) { +// // return NSCellHitContentArea; +// // } +// // +// // // Did we hit the sub title? +// // NSAttributedString *attributedSubTitle = [self attributedSubTitle]; +// // if ([attributedSubTitle length] > 0) { +// // NSRect attributedSubTitleRect = [self rectForSubTitleBasedOnTitleRect:titleRect inBounds:cellFrame]; +// // if (NSMouseInRect(point, attributedSubTitleRect, [controlView isFlipped])) { +// // // Notice that this text isn't an editable area. Clicking on it won't begin an editing session. +// // return NSCellHitContentArea; +// // } +// // } +// +// // How about the info button? +// NSRect infoButtonRect = [self infoButtonRectForBounds:cellFrame]; +// if (NSMouseInRect(point, infoButtonRect, [controlView isFlipped])) { +// return NSCellHitContentArea | NSCellHitTrackableArea; +// } +// } +// +// return [super hitTestForEvent:event inRect:cellFrame ofView:controlView]; +//} + +//+ (BOOL)prefersTrackingUntilMouseUp { +// // NSCell returns NO for this by default. If you want to have trackMouse:inRect:ofView:untilMouseUp: always track until the mouse is up, then you MUST return YES. Otherwise, strange things will happen. +// return YES; +//} + +// Mouse tracking -- the only part we want to track is the "info" button +- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)flag { +// [self setControlView:controlView]; +// + NSRect infoButtonRect = [self infoButtonRectForBounds:cellFrame]; + if ([theEvent type] != NSLeftMouseUp) { + // This is VERY simple event tracking. We simply check to see if the mouse is in the "i" button or not and dispatch entered/exited mouse events + NSPoint point = [controlView convertPoint:[theEvent locationInWindow] fromView:nil]; + BOOL mouseInButton = NSMouseInRect(point, infoButtonRect, [controlView isFlipped]); + if (iMouseDownInInfoButton != mouseInButton) { + iMouseDownInInfoButton = mouseInButton; + [controlView setNeedsDisplayInRect:cellFrame]; + } + if ([theEvent type] == NSMouseEntered || [theEvent type] == NSMouseExited) { + [NSApp sendEvent:theEvent]; + } + // Note that we process mouse entered and exited events and dispatch them to properly handle updates + theEvent = [[controlView window] nextEventMatchingMask:(NSLeftMouseUpMask | NSLeftMouseDraggedMask | NSMouseEnteredMask | NSMouseExitedMask)]; + } + + // Another way of implementing the above code would be to keep an NSButtonCell as an ivar, and simply call trackMouse:inRect:ofView:untilMouseUp: on it, if the tracking area was inside of it. + + NSPoint locationOfTouch = [controlView convertPoint:[theEvent locationInWindow] fromView:nil]; + + BOOL mouseInButton = NSMouseInRect(locationOfTouch, [self infoButtonRectForBounds:cellFrame], [controlView isFlipped]); + if (mouseInButton) { + // show menu + NSMenu *menu = [self menuForEvent:theEvent inRect:cellFrame ofView:controlView]; + if (menu){ + [NSMenu popUpContextMenu:menu withEvent:theEvent forView:controlView]; + } + } + + if (iMouseDownInInfoButton) { + // Send the action, and redisplay + iMouseDownInInfoButton = NO; + [controlView setNeedsDisplayInRect:cellFrame]; + } + + return [super trackMouse:theEvent inRect:cellFrame ofView:controlView untilMouseUp:flag]; + + +// +// // We return YES since the mouse was released while we were tracking. Not returning YES when you processed the mouse up is an easy way to introduce bugs! +// return YES; +} + + +// Mouse movement tracking -- we have a custom NSOutlineView subclass that automatically lets us add mouseEntered:/mouseExited: support to any cell! +- (void)addTrackingAreasForView:(NSView *)controlView inRect:(NSRect)cellFrame withUserInfo:(NSDictionary *)userInfo mouseLocation:(NSPoint)mouseLocation { + NSRect infoButtonRect = [self infoButtonRectForBounds:cellFrame]; + + NSTrackingAreaOptions options = NSTrackingEnabledDuringMouseDrag | NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways; + + BOOL mouseIsInside = NSMouseInRect(mouseLocation, infoButtonRect, [controlView isFlipped]); + if (mouseIsInside) { + options |= NSTrackingAssumeInside; + [controlView setNeedsDisplayInRect:cellFrame]; + } + + // We make the view the owner, and it delegates the calls back to the cell after it is properly setup for the corresponding row/column in the outlineview + NSTrackingArea *area = [[NSTrackingArea alloc] initWithRect:infoButtonRect options:options owner:controlView userInfo:userInfo]; + [controlView addTrackingArea:area]; + [area release]; +} + +- (void)mouseEntered:(NSEvent *)event { + iMouseHoveredInInfoButton = YES; + [(NSControl *)[self controlView] updateCell:self]; +} + +- (void)mouseExited:(NSEvent *)event { + iMouseHoveredInInfoButton = NO; + [(NSControl *)[self controlView] updateCell:self]; +} + + + @end diff --git a/PBSourceViewItem.h b/PBSourceViewItem.h index 012eef9..1547fd6 100644 --- a/PBSourceViewItem.h +++ b/PBSourceViewItem.h @@ -20,7 +20,10 @@ BOOL isGroupItem; BOOL isUncollapsible; + + BOOL showsActionButton; } +@property (nonatomic) BOOL showsActionButton; + (id)groupItemWithTitle:(NSString *)title; + (id)itemWithRevSpec:(PBGitRevSpecifier *)revSpecifier; diff --git a/PBSourceViewItem.m b/PBSourceViewItem.m index 5e4f881..8c810c0 100644 --- a/PBSourceViewItem.m +++ b/PBSourceViewItem.m @@ -12,6 +12,7 @@ @implementation PBSourceViewItem @synthesize parent, title, isGroupItem, children, revSpecifier, isUncollapsible; +@synthesize showsActionButton; @dynamic icon; - (id)init diff --git a/PBStashController.h b/PBStashController.h new file mode 100644 index 0000000..f6f6a60 --- /dev/null +++ b/PBStashController.h @@ -0,0 +1,31 @@ +// +// PBStashController.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-27. +// Copyright (c) 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBGitStash.h" + +@class PBGitRepository; + +@interface PBStashController : NSObject { + NSArray *stashes; +@private + PBGitRepository *repository; +} +@property (nonatomic, retain, readonly) NSArray *stashes; + +- (id) initWithRepository:(PBGitRepository *) repo; + +- (void) reload; + +- (NSArray *) menu; + +// actions +- (void) stashLocalChanges; +- (void) clearAllStashes; + +@end diff --git a/PBStashController.m b/PBStashController.m new file mode 100644 index 0000000..eccde18 --- /dev/null +++ b/PBStashController.m @@ -0,0 +1,110 @@ +// +// PBStashController.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-27. +// Copyright (c) 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBStashController.h" +#import "PBGitRepository.h" +#import "PBCommand.h" +#import "PBCommandWithParameter.h" + +static NSString * const kCommandName = @"stash"; + +@interface PBStashController() +@property (nonatomic, retain) NSArray *stashes; +@end + + + +@implementation PBStashController +@synthesize stashes; + +- (id) initWithRepository:(PBGitRepository *) repo { + if (self = [super init]){ + repository = [repo retain]; + } + return self; +} + +- (void)dealloc { + [repository release]; + [stashes release]; + [super dealloc]; +} + +- (void) reload { + NSArray *arguments = [NSArray arrayWithObjects:kCommandName, @"list", nil]; + NSString *output = [repository outputInWorkdirForArguments:arguments]; + NSArray *lines = [output componentsSeparatedByString:@"\n"]; + + NSMutableArray *loadedStashes = [[NSMutableArray alloc] initWithCapacity:[lines count]]; + + for (NSString *stashLine in lines) { + if ([stashLine length] == 0) + continue; + PBGitStash *stash = [[PBGitStash alloc] initWithRawStashLine:stashLine]; + [loadedStashes addObject:stash]; + [stash release]; + } + + self.stashes = loadedStashes; + [loadedStashes release]; +} + +#pragma mark Actions + +- (void) stashLocalChanges { + NSArray *args = [NSArray arrayWithObject:kCommandName]; + PBCommand *command = [[PBCommand alloc] initWithDisplayName:@"Stash local changes..." parameters:args repository:repository]; + command.commandTitle = command.displayName; + command.commandDescription = @"Stashing local changes"; + + PBCommandWithParameter *cmd = [[PBCommandWithParameter alloc] initWithCommand:command parameterName:@"save" parameterDisplayName:@"Stash message (optional)"]; + [command release]; + + [cmd invoke]; + [cmd release]; +} + +- (void) clearAllStashes { + PBCommand *command = [[PBCommand alloc] initWithDisplayName:@"Clear stashes" parameters:[NSArray arrayWithObjects:kCommandName, @"clear", nil] repository:repository]; + command.commandTitle = command.displayName; + command.commandDescription = @"Clearing stashes"; + [command invoke]; + [command release]; +} + +#pragma mark Menu + +- (NSArray *) menu { + NSMutableArray *array = [[NSMutableArray alloc] init]; + + NSMenuItem *stashChanges = [[NSMenuItem alloc] initWithTitle:@"Stash local changes..." action:@selector(stashLocalChanges) keyEquivalent:@""]; + [stashChanges setTarget:self]; + NSMenuItem *clearStashes = [[NSMenuItem alloc] initWithTitle:@"Clear stashes" action:@selector(clearAllStashes) keyEquivalent:@""]; + [clearStashes setTarget:self]; + + [array addObject:stashChanges]; + [array addObject:clearStashes]; + + return array; +} + +- (BOOL) validateMenuItem:(NSMenuItem *) item { + SEL action = [item action]; + BOOL shouldBeEnabled = YES; + + if (action == @selector(stashLocalChanges)) { + //TODO: check if we have unstaged changes + } else if (action == @selector(clearAllStashes)) { + shouldBeEnabled = [self.stashes count] > 0; + } + + return shouldBeEnabled; +} + + +@end diff --git a/PBViewController.h b/PBViewController.h index c523de7..ec5dbd4 100644 --- a/PBViewController.h +++ b/PBViewController.h @@ -37,6 +37,6 @@ - (void)viewLoaded; - (NSResponder *)firstResponder; -- (IBAction) refresh:(id)sender; +- (IBAction) refresh:(id)sender; @end diff --git a/PBViewController.m b/PBViewController.m index 82f6f7c..77e4f3f 100644 --- a/PBViewController.m +++ b/PBViewController.m @@ -44,15 +44,16 @@ return nil; } -- (IBAction) refresh: sender -{ -} - // The next methods should be implemented in the subclass if necessary - (void)updateView { } +- (IBAction) refresh:(id)sender +{ + return; +} + - (void)viewLoaded { } diff --git a/View/CellTrackingRect.h b/View/CellTrackingRect.h new file mode 100644 index 0000000..83aec4c --- /dev/null +++ b/View/CellTrackingRect.h @@ -0,0 +1,64 @@ +/* + + File: CellTrackingRect.h + + Abstract: This file provides a simple informal protocol for an NSCell. + If the cell implements these methods, it can automatically respond + to tracking area events generated by the TrackableOutlineView. + + Version: 1.0 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by + Apple Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. + may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2006-2007 Apple Inc. All Rights Reserved. + */ + +#import + +@interface NSCell (CellTrackingRect) + +/* When called by the control, it is the cell's responsibility to add tracking areas that it wishes to respond to. The cell will then get the appropriate mouse messages sent to it from the control. The owner for the NSTrackingArea must be the control. The userInfo can be copied and have additional things added to it by the cell, if required. +*/ +- (void)addTrackingAreasForView:(NSView *)view inRect:(NSRect)cellFrame withUserInfo:(NSDictionary *)userInfo mouseLocation:(NSPoint)currentPoint; + +- (void)mouseEntered:(NSEvent *)event; +- (void)mouseExited:(NSEvent *)event; + +@end + diff --git a/View/PBArgumentPicker.h b/View/PBArgumentPicker.h new file mode 100644 index 0000000..a273efa --- /dev/null +++ b/View/PBArgumentPicker.h @@ -0,0 +1,24 @@ +// +// PBArgumentPicker.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface PBArgumentPicker : NSView { + IBOutlet NSTextField *textField; + IBOutlet NSTextField *label; + IBOutlet NSButton *okButton; + IBOutlet NSButton *cancelButton; +} +@property (nonatomic, retain, readonly) NSTextField *textField; +@property (nonatomic, retain, readonly) NSTextField *label; +@property (nonatomic, retain, readonly) NSButton *okButton; +@property (nonatomic, retain, readonly) NSButton *cancelButton; + + +@end diff --git a/View/PBArgumentPicker.m b/View/PBArgumentPicker.m new file mode 100644 index 0000000..2902715 --- /dev/null +++ b/View/PBArgumentPicker.m @@ -0,0 +1,27 @@ +// +// PBArgumentPicker.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBArgumentPicker.h" + + +@implementation PBArgumentPicker +@synthesize okButton; +@synthesize cancelButton; +@synthesize textField; +@synthesize label; + +- (id)initWithFrame:(NSRect)frame { + self = [super initWithFrame:frame]; + if (self) { + // Initialization code here. + } + return self; +} + + +@end diff --git a/View/TrackableOutlineView.h b/View/TrackableOutlineView.h new file mode 100644 index 0000000..a384d80 --- /dev/null +++ b/View/TrackableOutlineView.h @@ -0,0 +1,58 @@ +/* + + File: TrackableOutlineView.h + + Abstract: This TrackableOutlineView class declaration. + + Version: 1.0 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by + Apple Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. + may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2006-2007 Apple Inc. All Rights Reserved. +*/ + +#import + +@interface TrackableOutlineView : NSOutlineView +{ +@private + NSInteger iMouseRow, iMouseCol; + NSCell *iMouseCell; +} +@end diff --git a/View/TrackableOutlineView.m b/View/TrackableOutlineView.m new file mode 100644 index 0000000..6af3925 --- /dev/null +++ b/View/TrackableOutlineView.m @@ -0,0 +1,185 @@ +/* + + File: TrackableOutlineView.m + + Abstract: The TrackableOutlineView provides an implementation of updateTrackingAreas + that automatically delegates to cells which implement the informal + CellTrackingRect protocol. + + Version: 1.0 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by + Apple Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. + may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2006-2007 Apple Inc. All Rights Reserved. + */ + +#import "TrackableOutlineView.h" + +#import +#import "CellTrackingRect.h" +#import "PBGitSidebarController.h" + +@implementation TrackableOutlineView + +- (id)init { + self = [super init]; + if (self) { + iMouseRow = -1; + iMouseCol = -1; + } + return self; +} + +- (id)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + if (self) { + iMouseRow = -1; + iMouseCol = -1; + } + return self; +} + +- (void)dealloc { + [iMouseCell release]; + [super dealloc]; +} + +// Tracking rect support + +- (void)updateTrackingAreas { + for (NSTrackingArea *area in [self trackingAreas]) { + // We have to uniquely identify our own tracking areas + if (([area owner] == self) && ([[area userInfo] objectForKey:@"Row"] != nil)) { + [self removeTrackingArea:area]; + } + } + + // Find the visible cells that have a non-empty tracking rect and add rects for each of them + NSRange visibleRows = [self rowsInRect:[self visibleRect]]; + NSIndexSet *visibleColIndexes = [self columnIndexesInRect:[self visibleRect]]; + + NSPoint mouseLocation = [self convertPoint:[[self window] convertScreenToBase:[NSEvent mouseLocation]] fromView:nil]; + NSInteger row; + for (row = visibleRows.location; row < visibleRows.location + visibleRows.length; row++ ) { + // If it is a "full width" cell, we don't have to go through the rows + NSCell *fullWidthCell = [self preparedCellAtColumn:-1 row:row]; + if (fullWidthCell) { + if ([fullWidthCell respondsToSelector:@selector(addTrackingAreasForView:inRect:withUserInfo:mouseLocation:)]) { + NSInteger col = -1; + NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInteger:col], @"Col", [NSNumber numberWithInteger:row], @"Row", nil]; + [fullWidthCell addTrackingAreasForView:self inRect:[self frameOfCellAtColumn:col row:row] withUserInfo:userInfo mouseLocation:mouseLocation]; + } + } else { + NSInteger col; + for (col = [visibleColIndexes firstIndex]; col != NSNotFound; col = [visibleColIndexes indexGreaterThanIndex:col]) { + NSCell *cell = [self preparedCellAtColumn:col row:row]; + if ([cell respondsToSelector:@selector(addTrackingAreasForView:inRect:withUserInfo:mouseLocation:)]) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInteger:col], @"Col", [NSNumber numberWithInteger:row], @"Row", nil]; + [cell addTrackingAreasForView:self inRect:[self frameOfCellAtColumn:col row:row] withUserInfo:userInfo mouseLocation:mouseLocation]; + } + } + } + } +} + +- (void)mouseEntered:(NSEvent *)event { + // Delegate this to the appropriate cell. In order to allow the cell to maintain state, we copy it and use the copy until the mouse is moved outside of the cell. + NSDictionary *userInfo = [event userData]; + NSNumber *row = [userInfo valueForKey:@"Row"]; + NSNumber *col = [userInfo valueForKey:@"Col"]; + if (row && col) { + NSInteger rowVal = [row integerValue]; + NSInteger colVal = [col integerValue]; + NSCell *cell = [self preparedCellAtColumn:colVal row:rowVal]; + // Only set the mouseCell properties AFTER calling preparedCellAtColumn:row:. + if (iMouseCell != cell) { + [iMouseCell release]; + // Store off the col/row + iMouseCol = colVal; + iMouseRow = rowVal; + // Store a COPY of the cell for use when tracking in an area + iMouseCell = [cell copy]; + [iMouseCell setControlView:self]; + if ([iMouseCell respondsToSelector:@selector(mouseEntered:)]) { + [iMouseCell mouseEntered:event]; + } + } + } +} + +- (void)mouseExited:(NSEvent *)event { + NSDictionary *userInfo = [event userData]; + NSNumber *row = [userInfo valueForKey:@"Row"]; + NSNumber *col = [userInfo valueForKey:@"Col"]; + if (row && col) { + NSCell *cell = [self preparedCellAtColumn:[col integerValue] row:[row integerValue]]; + [cell setControlView:self]; + if ([cell respondsToSelector:@selector(mouseExited:)]) { + [cell mouseExited:event]; + } + // We are now done with the copied cell + [iMouseCell release]; + iMouseCell = nil; + iMouseCol = -1; + iMouseRow = -1; + } +} + +/* Since NSTableView/NSOutineView uses the same cell to "stamp" out each row, we need to send the mouseEntered/mouseExited events each time it is drawn. The easy hook for this is the preparedCell method. +*/ +- (NSCell *)preparedCellAtColumn:(NSInteger)column row:(NSInteger)row { + // We check if the selectedCell is nil or not -- the selectedCell is a cell that is currently being edited or tracked. We don't want to return our override if we are in that state. + if ([self selectedCell] == nil && (row == iMouseRow) && (column == iMouseCol)) { + return iMouseCell; + } else { + return [super preparedCellAtColumn:column row:row]; + } +} + +/* In order for the cell to properly update itself with an "updateCell:" call, we must handle the "mouseCell" as a special case +*/ +- (void)updateCell:(NSCell *)aCell { + if (aCell == iMouseCell) { + [self setNeedsDisplayInRect:[self frameOfCellAtColumn:iMouseCol row:iMouseRow]]; + } else { + [super updateCell:aCell]; + } +} + +@end diff --git a/html/lib/md5.js b/html/lib/md5.js index 36fc1c2..46d2aab 100644 --- a/html/lib/md5.js +++ b/html/lib/md5.js @@ -1,256 +1,256 @@ -/* - * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message - * Digest Algorithm, as defined in RFC 1321. - * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for more info. - */ - -/* - * Configurable variables. You may need to tweak these to be compatible with - * the server-side, but the defaults work in most cases. - */ -var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ -var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ -var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ - -/* - * These are the functions you'll usually want to call - * They take string arguments and return either hex or base-64 encoded strings - */ -function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));} -function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));} -function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));} -function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); } -function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); } -function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); } - -/* - * Perform a simple self-test to see if the VM is working - */ -function md5_vm_test() -{ - return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72"; -} - -/* - * Calculate the MD5 of an array of little-endian words, and a bit length - */ -function core_md5(x, len) -{ - /* append padding */ - x[len >> 5] |= 0x80 << ((len) % 32); - x[(((len + 64) >>> 9) << 4) + 14] = len; - - var a = 1732584193; - var b = -271733879; - var c = -1732584194; - var d = 271733878; - - for(var i = 0; i < x.length; i += 16) - { - var olda = a; - var oldb = b; - var oldc = c; - var oldd = d; - - a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); - d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); - c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); - b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); - a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); - d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); - c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); - b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); - a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); - d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); - c = md5_ff(c, d, a, b, x[i+10], 17, -42063); - b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); - a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); - d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); - c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); - b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); - - a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); - d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); - c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); - b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); - a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); - d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); - c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); - b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); - a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); - d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); - c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); - b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); - a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); - d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); - c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); - b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); - - a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); - d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); - c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); - b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); - a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); - d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); - c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); - b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); - a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); - d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); - c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); - b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); - a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); - d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); - c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); - b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); - - a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); - d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); - c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); - b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); - a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); - d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); - c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); - b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); - a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); - d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); - c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); - b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); - a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); - d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); - c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); - b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); - - a = safe_add(a, olda); - b = safe_add(b, oldb); - c = safe_add(c, oldc); - d = safe_add(d, oldd); - } - return Array(a, b, c, d); - -} - -/* - * These functions implement the four basic operations the algorithm uses. - */ -function md5_cmn(q, a, b, x, s, t) -{ - return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); -} -function md5_ff(a, b, c, d, x, s, t) -{ - return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); -} -function md5_gg(a, b, c, d, x, s, t) -{ - return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); -} -function md5_hh(a, b, c, d, x, s, t) -{ - return md5_cmn(b ^ c ^ d, a, b, x, s, t); -} -function md5_ii(a, b, c, d, x, s, t) -{ - return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); -} - -/* - * Calculate the HMAC-MD5, of a key and some data - */ -function core_hmac_md5(key, data) -{ - var bkey = str2binl(key); - if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz); - - var ipad = Array(16), opad = Array(16); - for(var i = 0; i < 16; i++) - { - ipad[i] = bkey[i] ^ 0x36363636; - opad[i] = bkey[i] ^ 0x5C5C5C5C; - } - - var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz); - return core_md5(opad.concat(hash), 512 + 128); -} - -/* - * Add integers, wrapping at 2^32. This uses 16-bit operations internally - * to work around bugs in some JS interpreters. - */ -function safe_add(x, y) -{ - var lsw = (x & 0xFFFF) + (y & 0xFFFF); - var msw = (x >> 16) + (y >> 16) + (lsw >> 16); - return (msw << 16) | (lsw & 0xFFFF); -} - -/* - * Bitwise rotate a 32-bit number to the left. - */ -function bit_rol(num, cnt) -{ - return (num << cnt) | (num >>> (32 - cnt)); -} - -/* - * Convert a string to an array of little-endian words - * If chrsz is ASCII, characters >255 have their hi-byte silently ignored. - */ -function str2binl(str) -{ - var bin = Array(); - var mask = (1 << chrsz) - 1; - for(var i = 0; i < str.length * chrsz; i += chrsz) - bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32); - return bin; -} - -/* - * Convert an array of little-endian words to a string - */ -function binl2str(bin) -{ - var str = ""; - var mask = (1 << chrsz) - 1; - for(var i = 0; i < bin.length * 32; i += chrsz) - str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask); - return str; -} - -/* - * Convert an array of little-endian words to a hex string. - */ -function binl2hex(binarray) -{ - var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; - var str = ""; - for(var i = 0; i < binarray.length * 4; i++) - { - str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + - hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF); - } - return str; -} - -/* - * Convert an array of little-endian words to a base-64 string - */ -function binl2b64(binarray) -{ - var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - var str = ""; - for(var i = 0; i < binarray.length * 4; i += 3) - { - var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16) - | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 ) - | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF); - for(var j = 0; j < 4; j++) - { - if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; - else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); - } - } - return str; -} +/* + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for more info. + */ + +/* + * Configurable variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + */ +var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ +var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ +var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ + +/* + * These are the functions you'll usually want to call + * They take string arguments and return either hex or base-64 encoded strings + */ +function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));} +function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));} +function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));} +function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); } +function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); } +function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); } + +/* + * Perform a simple self-test to see if the VM is working + */ +function md5_vm_test() +{ + return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72"; +} + +/* + * Calculate the MD5 of an array of little-endian words, and a bit length + */ +function core_md5(x, len) +{ + /* append padding */ + x[len >> 5] |= 0x80 << ((len) % 32); + x[(((len + 64) >>> 9) << 4) + 14] = len; + + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + + for(var i = 0; i < x.length; i += 16) + { + var olda = a; + var oldb = b; + var oldc = c; + var oldd = d; + + a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); + d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); + c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); + b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); + a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); + d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); + c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); + b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); + a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); + d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); + c = md5_ff(c, d, a, b, x[i+10], 17, -42063); + b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); + a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); + d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); + c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); + b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); + + a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); + d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); + c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); + b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); + a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); + d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); + c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); + b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); + a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); + d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); + c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); + b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); + a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); + d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); + c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); + b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); + + a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); + d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); + c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); + b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); + a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); + d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); + c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); + b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); + a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); + d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); + c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); + b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); + a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); + d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); + c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); + b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); + + a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); + d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); + c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); + b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); + a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); + d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); + c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); + b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); + a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); + d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); + c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); + b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); + a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); + d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); + c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); + b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + } + return Array(a, b, c, d); + +} + +/* + * These functions implement the four basic operations the algorithm uses. + */ +function md5_cmn(q, a, b, x, s, t) +{ + return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); +} +function md5_ff(a, b, c, d, x, s, t) +{ + return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); +} +function md5_gg(a, b, c, d, x, s, t) +{ + return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); +} +function md5_hh(a, b, c, d, x, s, t) +{ + return md5_cmn(b ^ c ^ d, a, b, x, s, t); +} +function md5_ii(a, b, c, d, x, s, t) +{ + return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); +} + +/* + * Calculate the HMAC-MD5, of a key and some data + */ +function core_hmac_md5(key, data) +{ + var bkey = str2binl(key); + if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz); + + var ipad = Array(16), opad = Array(16); + for(var i = 0; i < 16; i++) + { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz); + return core_md5(opad.concat(hash), 512 + 128); +} + +/* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ +function safe_add(x, y) +{ + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); +} + +/* + * Bitwise rotate a 32-bit number to the left. + */ +function bit_rol(num, cnt) +{ + return (num << cnt) | (num >>> (32 - cnt)); +} + +/* + * Convert a string to an array of little-endian words + * If chrsz is ASCII, characters >255 have their hi-byte silently ignored. + */ +function str2binl(str) +{ + var bin = Array(); + var mask = (1 << chrsz) - 1; + for(var i = 0; i < str.length * chrsz; i += chrsz) + bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32); + return bin; +} + +/* + * Convert an array of little-endian words to a string + */ +function binl2str(bin) +{ + var str = ""; + var mask = (1 << chrsz) - 1; + for(var i = 0; i < bin.length * 32; i += chrsz) + str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask); + return str; +} + +/* + * Convert an array of little-endian words to a hex string. + */ +function binl2hex(binarray) +{ + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i++) + { + str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + + hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF); + } + return str; +} + +/* + * Convert an array of little-endian words to a base-64 string + */ +function binl2b64(binarray) +{ + var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i += 3) + { + var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16) + | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 ) + | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF); + for(var j = 0; j < 4; j++) + { + if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; + else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); + } + } + return str; +} diff --git a/sourceListAction.png b/sourceListAction.png new file mode 100644 index 0000000..9122fc1 Binary files /dev/null and b/sourceListAction.png differ diff --git a/sourceListActionOver.png b/sourceListActionOver.png new file mode 100644 index 0000000..70e0cb0 Binary files /dev/null and b/sourceListActionOver.png differ diff --git a/stash-icon.png b/stash-icon.png new file mode 100644 index 0000000..d861fb2 Binary files /dev/null and b/stash-icon.png differ diff --git a/submodule-empty.png b/submodule-empty.png new file mode 100644 index 0000000..c012e61 Binary files /dev/null and b/submodule-empty.png differ diff --git a/submodule-matching-index.png b/submodule-matching-index.png new file mode 100644 index 0000000..42d25ba Binary files /dev/null and b/submodule-matching-index.png differ diff --git a/submodule-notmatching-index.png b/submodule-notmatching-index.png new file mode 100644 index 0000000..d5abd30 Binary files /dev/null and b/submodule-notmatching-index.png differ