From be373b0ace9694c350e9a6a62d7f0a94bb3415ab Mon Sep 17 00:00:00 2001 From: Matt Connolly Date: Fri, 22 Oct 2010 07:01:55 +1000 Subject: [PATCH 01/23] Adding code to support SVN fetch,rebase,dcommit buttons and sensing of svn-remote configuration in repository. No implementation of `git svn` commands yet, just code for the buttons. --- PBGitConfig.h | 4 ++++ PBGitConfig.m | 33 ++++++++++++++++++++++++++++++ PBGitRepository.h | 5 +++++ PBGitRepository.m | 44 ++++++++++++++++++++++++++++++++++++++++ PBGitSidebarController.h | 7 +++++++ PBGitSidebarController.m | 22 ++++++++++++++++++++ 6 files changed, 115 insertions(+) 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/PBGitRepository.h b/PBGitRepository.h index 7599c6c..8df4888 100644 --- a/PBGitRepository.h +++ b/PBGitRepository.h @@ -69,6 +69,11 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { - (BOOL) deleteRemote:(PBGitRef *)ref; - (BOOL) deleteRef:(PBGitRef *)ref; +- (BOOL) hasSvnRemote; +- (BOOL) svnFetch:(NSString*)remoteName; +- (BOOL) svnRebase:(NSString*)remoteName; +- (BOOL) svnDcommit:(NSString*)commitURL; + - (NSFileHandle*) handleForCommand:(NSString*) cmd; - (NSFileHandle*) handleForArguments:(NSArray*) args; - (NSFileHandle *) handleInWorkDirForArguments:(NSArray *)args; diff --git a/PBGitRepository.m b/PBGitRepository.m index 3d4489b..db65155 100644 --- a/PBGitRepository.m +++ b/PBGitRepository.m @@ -885,6 +885,50 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; return YES; } +#pragma mark git svn commands + +/** + determines if the current repository has a git-svn configured remote + */ +- (BOOL) hasSvnRemote +{ + NSDictionary* configValues = [config listConfigValuesInDir:[self workingDirectory]]; + + for (NSString* key in configValues) { + if ([key hasPrefix:@"svn-remote."]) return YES; + } + return NO; +} + +/** + call `git svn fetch` with an optional remote name + + remoteName can be NULL + */ +- (BOOL) svnFetch:(NSString*)remoteName +{ + return YES; +} + +/** + call `git svn rebase` with an optional remote name + + remoteName can be NULL + */ +- (BOOL) svnRebase:(NSString*)remoteName +{ + return YES; +} + +/** + call `git svn dcommit` with optional commitURL + + commitURL can be NULL + */ +- (BOOL) svnDcommit:(NSString*)commitURL +{ + return YES; +} #pragma mark GitX Scripting diff --git a/PBGitSidebarController.h b/PBGitSidebarController.h index e2f712f..ec26569 100644 --- a/PBGitSidebarController.h +++ b/PBGitSidebarController.h @@ -20,6 +20,10 @@ IBOutlet NSPopUpButton *actionButton; IBOutlet NSSegmentedControl *remoteControls; + IBOutlet NSButton* svnFetchButton; + IBOutlet NSButton* svnRebaseButton; + IBOutlet NSButton* svnDcommitButton; + NSMutableArray *items; /* Specific things */ @@ -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 efcf6f1..679e2dc 100644 --- a/PBGitSidebarController.m +++ b/PBGitSidebarController.m @@ -371,6 +371,12 @@ enum { [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 @@ -408,5 +414,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 From 042289a7850badec990b8e082078dbbd9f3e7639 Mon Sep 17 00:00:00 2001 From: Matt Connolly Date: Fri, 22 Oct 2010 07:02:22 +1000 Subject: [PATCH 02/23] Updating XIB files with SVN fetch/rebase/dcommit buttons. --- English.lproj/RepositoryWindow.xib | 222 +++++++++++++---- PBGitHistoryView.xib | 72 ++++-- PBGitSidebarView.xib | 378 +++++++++++++++++++++++++++-- 3 files changed, 594 insertions(+), 78 deletions(-) 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/PBGitHistoryView.xib b/PBGitHistoryView.xib index 350a02f..3c9d8be 100644 --- a/PBGitHistoryView.xib +++ b/PBGitHistoryView.xib @@ -3,7 +3,7 @@ 1050 10F569 - 788 + 804 1038.29 461.00 @@ -15,13 +15,12 @@ YES - 788 - 788 + 804 + 804 YES - YES @@ -29,13 +28,8 @@ com.apple.WebKitIBPlugin - YES - - YES - - - YES - + PluginDependencyRecalculationVersion + YES @@ -118,6 +112,7 @@ 292 {{267, 3}, {71, 25}} + YES -2080244224 @@ -160,6 +155,7 @@ 268 {{206, 3}, {37, 25}} + YES -2080244224 @@ -184,6 +180,7 @@ 268 {{161, 3}, {37, 25}} + YES -2080244224 @@ -208,6 +205,7 @@ 268 {{116, 3}, {37, 25}} + YES -2080244224 @@ -232,6 +230,7 @@ 268 {{55, 3}, {37, 25}} + YES -2080244224 @@ -256,6 +255,7 @@ 268 {{10, 3}, {37, 25}} + YES -2080244224 @@ -280,6 +280,7 @@ 10 {{0, -2}, {955, 5}} + {0, 0} 67239424 @@ -308,6 +309,7 @@ {{0, 404}, {955, 30}} + PBGitGradientBarView @@ -325,6 +327,7 @@ 10 {{0, 144}, {955, 5}} + {0, 0} 67239424 @@ -357,12 +360,14 @@ 4352 {955, 130} + YES 256 {955, 17} + @@ -370,6 +375,7 @@ -2147483392 {{-26, 0}, {16, 17}} + YES @@ -496,7 +502,7 @@ - d 'de' MMMM 'de' yyyy HH:mm + d MMMM yyyy h:mm a NO @@ -625,6 +631,7 @@ {{0, 17}, {955, 130}} + @@ -635,6 +642,7 @@ -2147483392 {{837, 17}, {15, 179}} + _doScroller: 0.87603306770324707 @@ -644,6 +652,7 @@ -2147483392 {{0, 123}, {852, 15}} + 1 _doScroller: @@ -659,6 +668,7 @@ {955, 17} + @@ -668,6 +678,7 @@ {955, 147} + 560 @@ -688,6 +699,7 @@ {{740, 3}, {16, 16}} + 20746 100 @@ -696,6 +708,7 @@ 265 {{765, 2}, {180, 19}} + YES 343014976 @@ -757,6 +770,7 @@ 265 {{714, 3}, {43, 18}} + YES 67239424 @@ -793,6 +807,7 @@ 265 {{630, 5}, {80, 14}} + YES 68288064 @@ -814,6 +829,7 @@ 268 {{49, 2}, {57, 17}} + 1 YES @@ -839,6 +855,7 @@ 268 {{114, 2}, {103, 17}} + 2 YES @@ -860,6 +877,7 @@ 268 {{11, 2}, {30, 17}} + YES 67239424 @@ -878,11 +896,13 @@ {{0, 147}, {955, 24}} + PBGitGradientBarView {955, 171} + NSView @@ -895,6 +915,7 @@ 18 {955, 233} + YES @@ -988,6 +1009,7 @@ 4368 {216, 233} + YES @@ -1042,6 +1064,7 @@ {{1, 1}, {216, 233}} + @@ -1052,6 +1075,7 @@ 256 {{217, 1}, {15, 233}} + _doScroller: 0.99481862783432007 @@ -1061,6 +1085,7 @@ -2147483392 {{-100, -100}, {502, 15}} + 1 _doScroller: @@ -1070,6 +1095,7 @@ {233, 235} + 18 @@ -1097,6 +1123,7 @@ 289 {{41, 1.5}, {29, 19}} + YES -2080244224 @@ -1123,11 +1150,13 @@ {{639, 0}, {84, 24}} + NSView {{0, 211}, {723, 24}} + MGScopeBar @@ -1156,6 +1185,7 @@ {723, 210} + @@ -1166,17 +1196,20 @@ {{234, 0}, {723, 235}} + NSView {{-1, -1}, {957, 235}} + YES 2 {955, 233} + Tree @@ -1196,17 +1229,20 @@ {{0, 172}, {955, 233}} + NSView {955, 405} + 2 HistoryViewSplitView {955, 434} + NSView @@ -1988,7 +2024,9 @@ YES 0 - + + YES + @@ -2661,6 +2699,7 @@ 333.IBPluginDependency 337.IBAttributePlaceholdersKey 337.IBPluginDependency + 337.IBViewBoundsToFrameTransform 338.IBPluginDependency 34.CustomClassName 34.IBPluginDependency @@ -2804,6 +2843,9 @@ com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABC6AAAwdAAAA + com.apple.InterfaceBuilder.CocoaPlugin GitXTextFieldCell com.apple.InterfaceBuilder.CocoaPlugin @@ -2890,7 +2932,7 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.WebKitIBPlugin - {{2069, 399}, {955, 434}} + {{67, 422}, {955, 434}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -2928,7 +2970,7 @@ - 487 + 499 diff --git a/PBGitSidebarView.xib b/PBGitSidebarView.xib index cdf65f9..92a7d0b 100644 --- a/PBGitSidebarView.xib +++ b/PBGitSidebarView.xib @@ -2,13 +2,13 @@ 1050 - 10C540 - 759 - 1038.25 - 458.00 + 10F569 + 804 + 1038.29 + 461.00 com.apple.InterfaceBuilder.CocoaPlugin - 759 + 804 YES @@ -205,6 +205,70 @@ 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 +342,7 @@ -2076049856 134219776 - - LucidaGrande - 13 - 1044 - + -2034220801 163 @@ -353,7 +413,7 @@ - {200, 31} + {515, 31} NSView @@ -433,6 +493,30 @@ 51 + + + svnFetchButton + + + + 58 + + + + svnRebaseButton + + + + 59 + + + + svnDcommitButton + + + + 60 + @@ -522,6 +606,9 @@ YES + + + Source List Controls View @@ -584,6 +671,48 @@ + + 52 + + + YES + + + + + + 53 + + + YES + + + + + + 54 + + + YES + + + + + + 55 + + + + + 56 + + + + + 57 + + + @@ -609,6 +738,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 @@ -621,9 +762,9 @@ 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 +775,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 +835,18 @@ - 51 + 60 YES + + NSApplication + + IBProjectSource + NSApplication+GitXScripting.h + + NSOutlineView @@ -671,8 +858,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 +911,9 @@ remoteControls sourceListControlsView sourceView + svnDcommitButton + svnFetchButton + svnRebaseButton window @@ -690,9 +922,61 @@ 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 @@ -717,6 +1001,17 @@ PBViewController NSViewController + + refresh: + id + + + refresh: + + refresh: + id + + IBProjectSource PBViewController.h @@ -1084,6 +1379,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 @@ -1287,6 +1603,13 @@ view NSView + + view + + view + NSView + + IBFrameworkSource AppKit.framework/Headers/NSViewController.h @@ -1334,8 +1657,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} + From be0716ad0d0590c088084f74c7cf78899f3e3ac1 Mon Sep 17 00:00:00 2001 From: Matt Connolly Date: Tue, 26 Oct 2010 06:35:14 +1000 Subject: [PATCH 03/23] Adding code to do "git svn fetch/rebase/dcommit" --- PBGitRepository.h | 1 + PBGitRepository.m | 51 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/PBGitRepository.h b/PBGitRepository.h index 8df4888..b72d247 100644 --- a/PBGitRepository.h +++ b/PBGitRepository.h @@ -70,6 +70,7 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { - (BOOL) deleteRef:(PBGitRef *)ref; - (BOOL) hasSvnRemote; +- (NSArray*) svnRemotes; - (BOOL) svnFetch:(NSString*)remoteName; - (BOOL) svnRebase:(NSString*)remoteName; - (BOOL) svnDcommit:(NSString*)commitURL; diff --git a/PBGitRepository.m b/PBGitRepository.m index db65155..7b5ea16 100644 --- a/PBGitRepository.m +++ b/PBGitRepository.m @@ -891,13 +891,30 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; 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) { - if ([key hasPrefix:@"svn-remote."]) return YES; + 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 NO; + return [NSArray arrayWithArray:remotes]; } /** @@ -907,7 +924,15 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; */ - (BOOL) svnFetch:(NSString*)remoteName { - return YES; + 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; } /** @@ -917,7 +942,15 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; */ - (BOOL) svnRebase:(NSString*)remoteName { - return YES; + 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; } /** @@ -927,7 +960,15 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; */ - (BOOL) svnDcommit:(NSString*)commitURL { - return YES; + 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 From e067385125ce49bb2a7deffcdcad6bbead6f4240 Mon Sep 17 00:00:00 2001 From: Matt Connolly Date: Tue, 26 Oct 2010 06:35:35 +1000 Subject: [PATCH 04/23] connecting ui buttons to methods. --- PBGitSidebarView.xib | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/PBGitSidebarView.xib b/PBGitSidebarView.xib index 92a7d0b..85c93bb 100644 --- a/PBGitSidebarView.xib +++ b/PBGitSidebarView.xib @@ -517,6 +517,30 @@ 60 + + + svnFetch: + + + + 61 + + + + svnRebase: + + + + 62 + + + + svnDcommit: + + + + 63 + @@ -835,7 +859,7 @@ - 60 + 63 @@ -1400,6 +1424,13 @@ QuartzCore.framework/Headers/CIImageProvider.h + + NSObject + + IBFrameworkSource + ScriptingBridge.framework/Headers/SBApplication.h + + NSObject From 0a3b60066c0662c4097e2d1db22e95fb1080abb9 Mon Sep 17 00:00:00 2001 From: krt Date: Sat, 6 Nov 2010 13:20:13 +0100 Subject: [PATCH 05/23] Stashes are shown on in Side controlle --- Commands/PBCommand.h | 28 +++++++++++++ Commands/PBCommand.m | 44 ++++++++++++++++++++ Commands/PBCommandFactory.h | 13 ++++++ Commands/PBStashCommand.h | 19 +++++++++ Commands/PBStashCommand.m | 44 ++++++++++++++++++++ Commands/PBStashCommandFactory.h | 16 ++++++++ Commands/PBStashCommandFactory.m | 46 +++++++++++++++++++++ GitX.xcodeproj/project.pbxproj | 67 +++++++++++++++++++++++++++++++ Model/PBGitStash.h | 25 ++++++++++++ Model/PBGitStash.m | 51 +++++++++++++++++++++++ Model/PBPresentable.h | 13 ++++++ PBCommandMenuItem.h | 19 +++++++++ PBCommandMenuItem.m | 36 +++++++++++++++++ PBGitRepository.h | 3 ++ PBGitRepository.m | 37 ++++++++++++++++- PBGitSVStashItem.h | 20 +++++++++ PBGitSVStashItem.m | 45 +++++++++++++++++++++ PBGitSidebarController.h | 2 +- PBGitSidebarController.m | 48 ++++++++++++++++++---- stash-icon.png | Bin 0 -> 3395 bytes 20 files changed, 565 insertions(+), 11 deletions(-) create mode 100644 Commands/PBCommand.h create mode 100644 Commands/PBCommand.m create mode 100644 Commands/PBCommandFactory.h create mode 100644 Commands/PBStashCommand.h create mode 100644 Commands/PBStashCommand.m create mode 100644 Commands/PBStashCommandFactory.h create mode 100644 Commands/PBStashCommandFactory.m create mode 100644 Model/PBGitStash.h create mode 100644 Model/PBGitStash.m create mode 100644 Model/PBPresentable.h create mode 100644 PBCommandMenuItem.h create mode 100644 PBCommandMenuItem.m create mode 100644 PBGitSVStashItem.h create mode 100644 PBGitSVStashItem.m create mode 100644 stash-icon.png diff --git a/Commands/PBCommand.h b/Commands/PBCommand.h new file mode 100644 index 0000000..ee92b27 --- /dev/null +++ b/Commands/PBCommand.h @@ -0,0 +1,28 @@ +// +// PBCommand.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface PBCommand : NSObject { + // for the user to see what it triggers + NSString *displayName; + // shown during command execution + NSString *commandTitle; + NSString *commandDescription; + + NSArray *parameters; +} +@property (nonatomic, retain) NSString *commandTitle; +@property (nonatomic, retain) NSString *commandDescription; +@property (nonatomic, copy) NSString *displayName; +@property (nonatomic, retain, readonly) NSArray *parameters; + +- (id) initWithDisplayName:(NSString *) aDisplayName parameters:(NSArray *) params; +- (void) invoke; +@end diff --git a/Commands/PBCommand.m b/Commands/PBCommand.m new file mode 100644 index 0000000..db7a563 --- /dev/null +++ b/Commands/PBCommand.m @@ -0,0 +1,44 @@ +// +// PBCommand.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBCommand.h" + + +@implementation PBCommand +@synthesize displayName; +@synthesize parameters; +@synthesize commandDescription; +@synthesize commandTitle; + +- (id) initWithDisplayName:(NSString *) aDisplayName parameters:(NSArray *) params { + self = [super init]; + if (self != nil) { + self.displayName = aDisplayName; + parameters = [params retain]; + + // default values + self.commandTitle = @""; + self.commandDescription = @""; + } + return self; +} + + +- (void) dealloc { + [commandDescription release]; + [commandTitle release]; + [parameters release]; + [displayName release]; + [super dealloc]; +} + +- (void) invoke { + NSLog(@"Warning: Empty/abstrac command has been fired!"); +} + +@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/PBStashCommand.h b/Commands/PBStashCommand.h new file mode 100644 index 0000000..bf9d40d --- /dev/null +++ b/Commands/PBStashCommand.h @@ -0,0 +1,19 @@ +// +// PBStashCommand.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBCommand.h" +#import "PBGitRepository.h" + +@interface PBStashCommand : PBCommand { + PBGitRepository *repository; + NSArray *arguments; +} + +- initWithDisplayName:(NSString *) aDisplayName arguments:(NSArray *) args repository:(PBGitRepository *) repo; +@end diff --git a/Commands/PBStashCommand.m b/Commands/PBStashCommand.m new file mode 100644 index 0000000..53f9839 --- /dev/null +++ b/Commands/PBStashCommand.m @@ -0,0 +1,44 @@ +// +// PBStashCommand.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBStashCommand.h" +#import "PBRemoteProgressSheet.h" + +@interface PBStashCommand() +@property (nonatomic, retain) PBGitRepository *repository; +@property (nonatomic, retain) NSArray *arguments; +@end + + +@implementation PBStashCommand +@synthesize repository; +@synthesize arguments; + +- initWithDisplayName:(NSString *) aDisplayName arguments:(NSArray *) args repository:(PBGitRepository *) repo { + if (self = [super initWithDisplayName:aDisplayName parameters:[NSArray arrayWithObject:@"stash"]]) { + self.arguments = args; + self.repository = repo; + } + return self; +} + +- (void) dealloc { + [parameters release]; + [repository release]; + [super dealloc]; +} + + +- (void) invoke { + NSMutableArray *args = [[NSMutableArray alloc] initWithArray:super.parameters]; + [args addObjectsFromArray:self.arguments]; + [PBRemoteProgressSheet beginRemoteProgressSheetForArguments:args title:self.commandTitle description:self.commandDescription inRepository:self.repository]; + [args release]; +} + +@end diff --git a/Commands/PBStashCommandFactory.h b/Commands/PBStashCommandFactory.h new file mode 100644 index 0000000..291c47b --- /dev/null +++ b/Commands/PBStashCommandFactory.h @@ -0,0 +1,16 @@ +// +// 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..83f8e0f --- /dev/null +++ b/Commands/PBStashCommandFactory.m @@ -0,0 +1,46 @@ +// +// PBStashCommandFactory.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBStashCommandFactory.h" +#import "PBStashCommand.h" + +// model +#import "PBGitStash.h" + +@implementation PBStashCommandFactory + ++ (NSArray *) commandsForObject:(NSObject *) object repository:(PBGitRepository *) repository { + if (![object isKindOfClass:[PBGitStash class]]) { + return nil; + } + PBGitStash *stash = (PBGitStash *) object; + NSMutableArray *commands = [[NSMutableArray alloc] init]; + + NSArray *args = [NSArray arrayWithObjects:@"apply", [stash name], nil]; + PBStashCommand *command = [[PBStashCommand alloc] initWithDisplayName:@"Apply" arguments:args repository:repository]; + command.commandTitle = command.displayName; + command.commandDescription = [NSString stringWithFormat:@"Applying stash: '%@'", stash]; + [commands addObject:command]; + + args = [NSArray arrayWithObjects:@"pop", [stash name], nil]; + command = [[PBStashCommand alloc] initWithDisplayName:@"Pop" arguments:args repository:repository]; + command.commandTitle = command.displayName; + command.commandDescription = [NSString stringWithFormat:@"Poping stash: '%@'", stash]; + [commands addObject:command]; + + args = [NSArray arrayWithObjects:@"drop", [stash name], nil]; + command = [[PBStashCommand alloc] initWithDisplayName:@"Drop" arguments:args repository:repository]; + command.commandTitle = command.displayName; + command.commandDescription = [NSString stringWithFormat:@"Dropping stash: '%@'", stash]; + [commands addObject:command]; + + + return [commands autorelease]; +} + +@end diff --git a/GitX.xcodeproj/project.pbxproj b/GitX.xcodeproj/project.pbxproj index 71a441a..28ef783 100644 --- a/GitX.xcodeproj/project.pbxproj +++ b/GitX.xcodeproj/project.pbxproj @@ -24,6 +24,13 @@ 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 */; }; + 21230CB11284B26A0046E5A1 /* PBGitSVStashItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 21230CB01284B26A0046E5A1 /* PBGitSVStashItem.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 */; }; + 21230DEE12855A990046E5A1 /* PBStashCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 21230DED12855A990046E5A1 /* PBStashCommand.m */; }; 3BC07F4C0ED5A5C5009A7768 /* HistoryViewTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = 3BC07F4A0ED5A5C5009A7768 /* HistoryViewTemplate.png */; }; 3BC07F4D0ED5A5C5009A7768 /* CommitViewTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = 3BC07F4B0ED5A5C5009A7768 /* CommitViewTemplate.png */; }; 47DBDB580E94EDE700671A1E /* DBPrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 47DBDB570E94EDE700671A1E /* DBPrefsWindowController.m */; }; @@ -245,6 +252,21 @@ 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 = ""; }; + 21230CAF1284B26A0046E5A1 /* PBGitSVStashItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitSVStashItem.h; sourceTree = ""; }; + 21230CB01284B26A0046E5A1 /* PBGitSVStashItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitSVStashItem.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 = ""; }; + 21230DEC12855A990046E5A1 /* PBStashCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBStashCommand.h; sourceTree = ""; }; + 21230DED12855A990046E5A1 /* PBStashCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBStashCommand.m; 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 = ""; }; @@ -527,6 +549,8 @@ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( + 21230D991285524C0046E5A1 /* Commands */, + 21230D321284C4F10046E5A1 /* Model */, ); name = Classes; sourceTree = ""; @@ -567,6 +591,30 @@ name = Products; sourceTree = ""; }; + 21230D321284C4F10046E5A1 /* Model */ = { + isa = PBXGroup; + children = ( + 21230D331284C5080046E5A1 /* PBGitStash.h */, + 21230D341284C5080046E5A1 /* PBGitStash.m */, + 21230D4D1284C92E0046E5A1 /* PBPresentable.h */, + ); + path = Model; + sourceTree = ""; + }; + 21230D991285524C0046E5A1 /* Commands */ = { + isa = PBXGroup; + children = ( + 21230D9A128552720046E5A1 /* PBCommand.h */, + 21230D9B128552720046E5A1 /* PBCommand.m */, + 21230DEC12855A990046E5A1 /* PBStashCommand.h */, + 21230DED12855A990046E5A1 /* PBStashCommand.m */, + 21230D9D128552FA0046E5A1 /* PBStashCommandFactory.h */, + 21230D9E128552FA0046E5A1 /* PBStashCommandFactory.m */, + 21230DA0128553120046E5A1 /* PBCommandFactory.h */, + ); + path = Commands; + sourceTree = ""; + }; 29B97314FDCFA39411CA2CEA /* GitTest */ = { isa = PBXGroup; children = ( @@ -612,6 +660,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 */, @@ -744,6 +793,8 @@ D8FDDA63114335E8005647F6 /* PBGitSVRemoteBranchItem.m */, D8FDDA68114335E8005647F6 /* PBGitSVTagItem.h */, D8FDDA69114335E8005647F6 /* PBGitSVTagItem.m */, + 21230CAF1284B26A0046E5A1 /* PBGitSVStashItem.h */, + 21230CB01284B26A0046E5A1 /* PBGitSVStashItem.m */, D8FDDA60114335E8005647F6 /* PBGitSVOtherRevItem.h */, D8FDDA61114335E8005647F6 /* PBGitSVOtherRevItem.m */, D8FDDA5E114335E8005647F6 /* PBGitSVFolderItem.h */, @@ -938,6 +989,8 @@ F5FC43C30EBD050800191D80 /* PBRefContextDelegate.h */, F5FC43FC0EBD08EE00191D80 /* PBRefMenuItem.h */, F5FC43FD0EBD08EE00191D80 /* PBRefMenuItem.m */, + 21230DA81285550B0046E5A1 /* PBCommandMenuItem.h */, + 21230DA91285550B0046E5A1 /* PBCommandMenuItem.m */, ); name = History; sourceTree = ""; @@ -1114,7 +1167,14 @@ isa = PBXProject; buildConfigurationList = 26FC0A880875C7B200E6366F /* Build configuration list for PBXProject "GitX" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); mainGroup = 29B97314FDCFA39411CA2CEA /* GitTest */; projectDirPath = ""; projectRoot = ""; @@ -1181,6 +1241,7 @@ D8F01C4B12182F19007F729F /* GitX.sdef in Resources */, D8F4AB7912298CE200D6D53C /* rewindImage.pdf in Resources */, 02B41A60123E307F00DFC531 /* PBCommitHookFailedSheet.xib in Resources */, + 21230D821284D1CC0046E5A1 /* stash-icon.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1331,6 +1392,12 @@ D8B4DC571220D1E4004166D6 /* PBHistorySearchController.m in Sources */, D8712A00122B14EC00012334 /* GitXTextFieldCell.m in Sources */, 02B41A5E123E307200DFC531 /* PBCommitHookFailedSheet.m in Sources */, + 21230CB11284B26A0046E5A1 /* PBGitSVStashItem.m in Sources */, + 21230D351284C5080046E5A1 /* PBGitStash.m in Sources */, + 21230D9C128552720046E5A1 /* PBCommand.m in Sources */, + 21230D9F128552FA0046E5A1 /* PBStashCommandFactory.m in Sources */, + 21230DAA1285550B0046E5A1 /* PBCommandMenuItem.m in Sources */, + 21230DEE12855A990046E5A1 /* PBStashCommand.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 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..e2f08c6 --- /dev/null +++ b/Model/PBGitStash.m @@ -0,0 +1,51 @@ +// +// 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 self.name; +} + +- (NSString *) popupDescription { + return [self description]; +} + +@end diff --git a/Model/PBPresentable.h b/Model/PBPresentable.h new file mode 100644 index 0000000..299d208 --- /dev/null +++ b/Model/PBPresentable.h @@ -0,0 +1,13 @@ +// +// PBPresentable.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-06. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + + +@protocol PBPresentable +- (NSString *) displayDescription; +- (NSString *) popupDescription; +@end 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..3a080dd --- /dev/null +++ b/PBCommandMenuItem.m @@ -0,0 +1,36 @@ +// +// 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)]; + } + return self; +} + +- (void) dealloc { + [command release]; + [super dealloc]; +} + + +@end diff --git a/PBGitRepository.h b/PBGitRepository.h index 7599c6c..986c0aa 100644 --- a/PBGitRepository.h +++ b/PBGitRepository.h @@ -52,6 +52,8 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { PBGitRevSpecifier *_headRef; // Caching PBGitSHA* _headSha; + + NSArray *stashes; } - (void) cloneRepositoryToPath:(NSString *)path bare:(BOOL)isBare; @@ -90,6 +92,7 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { - (NSString *)gitIgnoreFilename; - (BOOL)isBareRepository; +- (void) reloadStashes; - (void) reloadRefs; - (void) addRef:(PBGitRef *)ref fromParameters:(NSArray *)params; - (void) lazyReload; diff --git a/PBGitRepository.m b/PBGitRepository.m index 3d4489b..2d18d5d 100644 --- a/PBGitRepository.m +++ b/PBGitRepository.m @@ -21,10 +21,18 @@ #import "GitXScriptingConstants.h" #import "PBHistorySearchController.h" +#import "PBGitStash.h" + NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; -@implementation PBGitRepository +@interface PBGitRepository() +@property (nonatomic, retain) NSArray *stashes; +@end + + +@implementation PBGitRepository +@synthesize stashes; @synthesize revisionList, branches, currentBranch, refs, hasChanged, config; @synthesize currentBranchFilter; @@ -247,6 +255,23 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; [refs setObject:[NSMutableArray arrayWithObject:ref] forKey:sha]; } +- (void) reloadStashes { + NSArray *arguments = [NSArray arrayWithObjects:@"stash", @"list", nil]; + NSString *output = [self outputInWorkdirForArguments:arguments]; + NSArray *lines = [output componentsSeparatedByString:@"\n"]; + + NSMutableArray *loadedStashes = [[NSMutableArray alloc] init]; + + for (NSString *stashLine in lines) { + PBGitStash *stash = [[PBGitStash alloc] initWithRawStashLine:stashLine]; + [loadedStashes addObject:stash]; + [stash release]; + } + + self.stashes = loadedStashes; + [loadedStashes release]; +} + - (void) reloadRefs { _headRef = nil; @@ -280,6 +305,8 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; [self willChangeValueForKey:@"refs"]; [self didChangeValueForKey:@"refs"]; + + [self reloadStashes]; [[[self windowController] window] setTitle:[self displayName]]; } @@ -1061,7 +1088,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 @@ -1138,6 +1166,11 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; return nil; } +- (void) dealloc { + [stashes release]; + [super dealloc]; +} + - (void) finalize { NSLog(@"Dealloc of repository"); diff --git a/PBGitSVStashItem.h b/PBGitSVStashItem.h new file mode 100644 index 0000000..e3cd134 --- /dev/null +++ b/PBGitSVStashItem.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 "PBGitStash.h" + + +@interface PBGitSVStashItem : PBSourceViewItem { + PBGitStash *stash; +} +@property (nonatomic, retain, readonly) PBGitStash *stash; + +- initWithStash:(PBGitStash *) aStash; +@end diff --git a/PBGitSVStashItem.m b/PBGitSVStashItem.m new file mode 100644 index 0000000..d91d069 --- /dev/null +++ b/PBGitSVStashItem.m @@ -0,0 +1,45 @@ +// +// PBGitSVStashItem.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-05. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBGitSVStashItem.h" + + +@implementation PBGitSVStashItem +@synthesize stash; + +#pragma mark - +#pragma mark Inits/dealloc +//--------------------------------------------------------------------------------------------- + +- initWithStash:(PBGitStash *) aStash { + if (self = [super init]) { + NSString *displayTitle = [NSString stringWithFormat:@"%@ (%@)", [aStash message], [aStash stashSourceMessage]]; + super.title = displayTitle; + stash = [aStash retain]; + } + return self; +} + +- (void) dealloc { + [stash release]; + [super dealloc]; +} + +//--------------------------------------------------------------------------------------------- +#pragma mark - + + +- (NSImage *) icon { + static NSImage *tagImage = nil; + if (!tagImage) + tagImage = [NSImage imageNamed:@"stash-icon.png"]; + + return tagImage; +} + +@end diff --git a/PBGitSidebarController.h b/PBGitSidebarController.h index e2f712f..68b5405 100644 --- a/PBGitSidebarController.h +++ b/PBGitSidebarController.h @@ -25,7 +25,7 @@ /* Specific things */ PBSourceViewItem *stage; - PBSourceViewItem *branches, *remotes, *tags, *others; + PBSourceViewItem *branches, *remotes, *tags, *others, *stashes; PBGitHistoryController *historyViewController; PBGitCommitController *commitViewController; diff --git a/PBGitSidebarController.m b/PBGitSidebarController.m index efcf6f1..81b696f 100644 --- a/PBGitSidebarController.m +++ b/PBGitSidebarController.m @@ -16,6 +16,12 @@ #import "PBAddRemoteSheet.h" #import "PBGitDefaults.h" #import "PBHistorySearchController.h" +#import "PBGitSVStashItem.h" + +#import "PBStashCommandFactory.h" +#import "PBCommandMenuItem.h" + +static NSString * const kObservingContextStashes = @"stashesChanged"; @interface PBGitSidebarController () @@ -51,6 +57,7 @@ [repository addObserver:self forKeyPath:@"currentBranch" options:0 context:@"currentBranchChange"]; [repository addObserver:self forKeyPath:@"branches" options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew) context:@"branchesModified"]; + [repository addObserver:self forKeyPath:@"stashes" options:NSKeyValueObservingOptionNew context:@"stashesChanged"]; [self menuNeedsUpdate:[actionButton menu]]; @@ -67,6 +74,7 @@ [repository removeObserver:self forKeyPath:@"currentBranch"]; [repository removeObserver:self forKeyPath:@"branches"]; + [repository removeObserver:self forKeyPath:@"stashes"]; [super closeView]; } @@ -76,10 +84,7 @@ if ([@"currentBranchChange" isEqualToString:context]) { [sourceView reloadData]; [self selectCurrentBranch]; - return; - } - - if ([@"branchesModified" isEqualToString:context]) { + } else if ([@"branchesModified" isEqualToString:context]) { NSInteger changeKind = [(NSNumber *)[change objectForKey:NSKeyValueChangeKindKey] intValue]; if (changeKind == NSKeyValueChangeInsertion) { @@ -95,10 +100,19 @@ for (PBGitRevSpecifier *rev in removedRevSpecs) [self removeRevSpec:rev]; } - return; + } else if ([@"stashesChanged" isEqualToString:context]) { // isEqualToString: is not needed here + [stashes.children removeAllObjects]; + NSArray *newStashes = [change objectForKey:NSKeyValueChangeNewKey]; + + for (PBGitStash *stash in newStashes) { + PBGitSVStashItem *item = [[PBGitSVStashItem alloc] initWithStash:stash]; + [stashes addChild:item]; + [item release]; + } + [sourceView reloadData]; + } else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } - - [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } - (PBSourceViewItem *) selectedItem @@ -170,6 +184,7 @@ [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]; } @@ -252,6 +267,7 @@ remotes = [PBSourceViewItem groupItemWithTitle:@"Remotes"]; tags = [PBSourceViewItem groupItemWithTitle:@"Tags"]; others = [PBSourceViewItem groupItemWithTitle:@"Other"]; + stashes = [PBSourceViewItem groupItemWithTitle:@"Stashes"]; for (PBGitRevSpecifier *rev in repository.branches) [self addRevSpec:rev]; @@ -261,6 +277,7 @@ [items addObject:remotes]; [items addObject:tags]; [items addObject:others]; + [items addObject:stashes]; [sourceView reloadData]; [sourceView expandItem:project]; @@ -328,7 +345,22 @@ - (NSMenu *) menuForRow:(NSInteger)row { PBSourceViewItem *viewItem = [sourceView itemAtRow:row]; - + if ([viewItem isKindOfClass:[PBGitSVStashItem class]]) { + PBGitSVStashItem *stashItem = (PBGitSVStashItem *) viewItem; + NSArray *commands = [PBStashCommandFactory commandsForObject:[stashItem stash] repository:historyViewController.repository]; + if (!commands) { + return nil; + } + NSMenu *menu = [[NSMenu alloc] init]; + for (PBCommand *command in commands) { + PBCommandMenuItem *item = [[PBCommandMenuItem alloc] initWithCommand:command]; + [item setEnabled:YES]; + [menu addItem:item]; + [item release]; + } + return menu; + } + PBGitRef *ref = [viewItem ref]; if (!ref) return nil; diff --git a/stash-icon.png b/stash-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d861fb23973ca802c42b9d8d1c715ea70435daf1 GIT binary patch literal 3395 zcmV-J4ZQM+P)5r000U^X+uL$Nkc;* zP;zf(X>4Tx0C)kNmUmPX*B8g%%xo{TU6vwc>AklFq%OTkl_mFQv@x1^BM1TV}0C2duqR=S6Xn?LjUp6xrb&~O43j*Nv zEr418u3H3zGns$s|L;SQD-ufpfWpxLJ03rmi*g~#S@{x?OrJ!Vo{}kJ7$ajbnjp%m zGEV!%=70KpVow?KvV}a4moSaFCQKV= zXBIPnpP$8-NG!rR+)R#`$7JVZi#Wn10DSspSrkx`)s~4C+0n+?(b2-z5-tDd^^cpM zz5W?wz5V3zGUCskL5!X++LzcbT23thtSPiMTfS&1I{|204}j|3FPi>70OSh+Xzlyz zdl<5LNtZ}OE>>3g`T3RtKG#xK(9i3CI(+v0d-&=+OWAp!Ysd8Ar*foO5~i%E+?=c& zshF87;&Ay)i~kOm zCIB-Z!^JGdti+UJsxgN!t(Y#%b<8kk67vyD#cE*9urAm@Y#cTXn~yERR$}Y1E!Yd# zo7hq8Ya9;8z!~A3Z~?e@Tn26#t`xT$*Ni)h>&K1Yrto;Y8r}@=h7ZGY@Dh9xekcA2 z{tSKqKZ<`tAQQ9+wgf*y0zpVvOQ<9qCY&Y=5XJ~ILHOG0j2XwBQ%7jM`P2tv~{#P+6CGu9Y;5!2hua>CG_v;z4S?CC1rc%807-x z8s$^ULkxsr$OvR)G0GUn7`GVjR5Vq*RQM{JRGL%DRgX~5SKp(4L49HleU9rK?wsN|$L8GCfHh1tA~lw29MI^|n9|hJ z^w$(=?$kW5IibbS^3=-Es?a*EHLgw5cGnhYS7@Kne#%s4dNH$@Rm?8tq>hG8fR0pW zzfP~tjINRHeBHIW&AJctNO~;2RJ{tlPQ6KeZT(RF<@$~KcMXUJEQ54|9R}S7(}qTd zv4$HA+YFx=sTu_uEj4O1x^GN1_Ap*-Tx)#81ZToB$u!w*a?KPrbudjgtugI0gUuYx z1ZKO<`pvQC&gMe%TJu2*iiMX&o<*a@uqDGX#B!}=o8@yWeX9hktybMuAFUm%v#jf^ z@7XBX1lg>$>9G0T*3_13TVs2}j%w#;x5}>F?uEUXJ>Pzh{cQ)DL#V?BhfaqNj!uqZ z$0o;dCw-@6r(I5iEIKQkRm!^LjCJ;QUgdn!`K^nii^S!a%Wtk0u9>cfU7yS~n#-SC zH+RHM*Nx-0-)+d9>7MMq&wa>4$AjZh>+#4_&y(j_?>XjW;+5fb#Ot}YwYS*2#e16V z!d}5X>x20C`xN{1`YQR(_pSDQ=%?$K=GW*q>F?mb%>QfvHXt})YrtTjW*|4PA#gIt zDQHDdS1=_wD!4lMQHW`XIHV&K4h;(37J7f4!93x-wlEMD7`83!LAX));_x3Ma1r4V zH4%>^Z6cRPc1O{olA;bry^i*dE{nc5-*~=serJq)Okzw!%yg_zYWi`#ol25V;v^kU#wN!mA5MPH z3FFjqrcwe^cBM>m+1wr6XFN|{1#g`1#xLiOrMjh-r#?w@OWT$Wgg6&&5F%x&L(6hXP*!%2{VOVIa)adIsGCtQITk9vCHD^izmgw;`&@D zcVTY3gpU49^+=7S>!rha?s+wNZ}MaEj~6Hw2n%|am@e70WNfM5(r=exmT{MLF4tMU zX8G_6uNC`OLMu~NcCOM}Rk&(&wg2ivYe;J{*Zj2BdTsgISLt?eJQu}$~QLORDCnMIdyYynPb_W zEx0YhEw{FMY&}%2SiZD;WLxOA)(U1tamB0cN!u@1+E?z~LE0hRF;o>&)xJ}I=a!xC ztJAA*)_B)6@6y<{Y1i~_-tK`to_m`1YVIxB`);3L-|hYW`&(-bYby`n4&)tpTo+T< z{VnU;hI;k-lKKw^g$IWYMIP#EaB65ctZ}%k5pI+=jvq-pa_u{x@7kLzn)Wv{noEv? zqtc^Kzfb=D*0JDYoyS?nn|?6(VOI;SrMMMpUD7()mfkkh9^c-7BIrbChiga6kCs0k zJgIZC=9KcOveTr~g{NoFEIl)IR&;jaT-v#j&ZN$J=i|=b=!)p-y%2oi(nY_E=exbS z&s=i5bn>#xz3Ke>~2=f&N;yEFGz-^boBexUH6@}b7V+Mi8+ZXR+R zIyLMw-18{v(Y+Dw$g^K^e|bMz_?Y^*a!h-y;fd{&ljDBl*PbqTI{HlXY-Xb9SH)j< zJvV;-!*8Cy^-RW1j=m7TnEk!M3&di(lymvt5O`3Q6?m74CTw#pC)$?j$p|Rg?KaS7h z(nPIRRZ1nt$Gt(NGTwJQ=XJB$Y+uD&{AX@%&Y7Q|ciFC8zxk|G9=#KlqTSZV*3#zI z=9+ZfJ;#;z8jZ#xV;IXEw#AFZ=Pw5*gN9{W31w4bqht58H2acf$9+yJ`tbYGb^SDEK6nmX}Sga|n(m1O}(4a2*GhZDTl0>D54zZCL_onxRx0 z!QZwSFTefRg;H70bn@_3w8iChdwruag=>{D;du_U)(p{1NO<8gdvQjQCpP2Aw8KvB^#sp zBSrG!*E>GJ`>mZq+L(ycH&UgF1k_@|VXpkA8I6@=WqFQak`|dg&!uS_ Date: Sat, 6 Nov 2010 13:21:04 +0100 Subject: [PATCH 06/23] Ignored hidden temp files --- .gitignore | 1 + 1 file changed, 1 insertion(+) 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 From cc5c93c2b63b5e27914dcff3c3b00f7771c9ca49 Mon Sep 17 00:00:00 2001 From: Tomasz Krasnyk Date: Sun, 7 Nov 2010 23:37:41 +0100 Subject: [PATCH 07/23] - stashes can be created with optional message - added clearing all stashes - added possibility to ignore files with given extension - submodules are now showed - submodules can be opened --- Commands/PBCommand.h | 14 +- Commands/PBCommand.m | 24 +- Commands/PBCommandWithParameter.h | 23 + Commands/PBCommandWithParameter.m | 40 + Commands/PBOpenDocumentCommand.h | 17 + Commands/PBOpenDocumentCommand.m | 26 + Commands/PBRemoteCommandFactory.h | 17 + Commands/PBRemoteCommandFactory.m | 38 + Commands/PBStashCommand.h | 19 - Commands/PBStashCommand.m | 44 - Commands/PBStashCommandFactory.h | 1 + Commands/PBStashCommandFactory.m | 64 +- Controller/PBArgumentPickerController.h | 25 + Controller/PBArgumentPickerController.m | 50 + GitX.xcodeproj/project.pbxproj | 86 +- Model/PBGitStash.m | 6 +- Model/PBGitSubmodule.h | 34 + Model/PBGitSubmodule.m | 113 +++ Model/PBPresentable.h | 3 +- PBArgumentPicker.xib | 1110 +++++++++++++++++++++++ PBEasyPipe.m | 10 +- PBGitIndexController.m | 25 + PBGitMenuItem.h | 20 + PBGitMenuItem.m | 62 ++ PBGitRepository.h | 3 + PBGitRepository.m | 30 +- PBGitSVStashItem.h | 20 - PBGitSVStashItem.m | 45 - PBGitSidebarController.h | 2 +- PBGitSidebarController.m | 53 +- PBRefController.m | 4 +- PBRefMenuItem.m | 15 +- View/PBArgumentPicker.h | 24 + View/PBArgumentPicker.m | 27 + submodule-empty.png | Bin 0 -> 3422 bytes submodule-matching-index.png | Bin 0 -> 3505 bytes submodule-notmatching-index.png | Bin 0 -> 425 bytes 37 files changed, 1916 insertions(+), 178 deletions(-) create mode 100644 Commands/PBCommandWithParameter.h create mode 100644 Commands/PBCommandWithParameter.m create mode 100644 Commands/PBOpenDocumentCommand.h create mode 100644 Commands/PBOpenDocumentCommand.m create mode 100644 Commands/PBRemoteCommandFactory.h create mode 100644 Commands/PBRemoteCommandFactory.m delete mode 100644 Commands/PBStashCommand.h delete mode 100644 Commands/PBStashCommand.m create mode 100644 Controller/PBArgumentPickerController.h create mode 100644 Controller/PBArgumentPickerController.m create mode 100644 Model/PBGitSubmodule.h create mode 100644 Model/PBGitSubmodule.m create mode 100644 PBArgumentPicker.xib create mode 100644 PBGitMenuItem.h create mode 100644 PBGitMenuItem.m delete mode 100644 PBGitSVStashItem.h delete mode 100644 PBGitSVStashItem.m create mode 100644 View/PBArgumentPicker.h create mode 100644 View/PBArgumentPicker.m create mode 100644 submodule-empty.png create mode 100644 submodule-matching-index.png create mode 100644 submodule-notmatching-index.png diff --git a/Commands/PBCommand.h b/Commands/PBCommand.h index ee92b27..4f63935 100644 --- a/Commands/PBCommand.h +++ b/Commands/PBCommand.h @@ -7,22 +7,28 @@ // #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; - NSArray *parameters; + NSMutableArray *parameters; } +@property (nonatomic, retain, readonly) PBGitRepository *repository; @property (nonatomic, retain) NSString *commandTitle; @property (nonatomic, retain) NSString *commandDescription; @property (nonatomic, copy) NSString *displayName; -@property (nonatomic, retain, readonly) NSArray *parameters; -- (id) initWithDisplayName:(NSString *) aDisplayName parameters:(NSArray *) params; +- (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 index db7a563..e427372 100644 --- a/Commands/PBCommand.m +++ b/Commands/PBCommand.m @@ -7,29 +7,39 @@ // #import "PBCommand.h" +#import "PBRemoteProgressSheet.h" +@interface PBCommand() +@property (nonatomic, retain) PBGitRepository *repository; +@end @implementation PBCommand @synthesize displayName; -@synthesize parameters; @synthesize commandDescription; @synthesize commandTitle; +@synthesize repository; - (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 = [params retain]; + parameters = [[NSMutableArray alloc] initWithArray:params]; // default values self.commandTitle = @""; self.commandDescription = @""; + self.repository = repo; } return self; } - (void) dealloc { + [repository release]; [commandDescription release]; [commandTitle release]; [parameters release]; @@ -37,8 +47,16 @@ [super dealloc]; } +- (NSArray *) allParameters { + return parameters; +} + +- (void) appendParameters:(NSArray *) params { + [parameters addObjectsFromArray:params]; +} + - (void) invoke { - NSLog(@"Warning: Empty/abstrac command has been fired!"); + [PBRemoteProgressSheet beginRemoteProgressSheetForArguments:[self allParameters] title:self.commandTitle description:self.commandDescription inRepository:self.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..934c6e3 --- /dev/null +++ b/Commands/PBRemoteCommandFactory.m @@ -0,0 +1,38 @@ +// +// 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" + + +@implementation PBRemoteCommandFactory + ++ (NSArray *) commandsForSubmodule:(PBGitSubmodule *) submodule inRepository:(PBGitRepository *) repository { + NSMutableArray *commands = [[NSMutableArray alloc] init]; + + NSString *repoPath = [repository workingDirectory]; + + NSString *path = [repoPath stringByAppendingPathComponent:[submodule path]]; + + PBOpenDocumentCommand *command = [[PBOpenDocumentCommand alloc] initWithDocumentAbsolutePath:path]; + command.commandTitle = command.displayName; + command.commandDescription = @"Opening document"; + [commands addObject:command]; + + 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/PBStashCommand.h b/Commands/PBStashCommand.h deleted file mode 100644 index bf9d40d..0000000 --- a/Commands/PBStashCommand.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// PBStashCommand.h -// GitX -// -// Created by Tomasz Krasnyk on 10-11-06. -// Copyright 2010 __MyCompanyName__. All rights reserved. -// - -#import -#import "PBCommand.h" -#import "PBGitRepository.h" - -@interface PBStashCommand : PBCommand { - PBGitRepository *repository; - NSArray *arguments; -} - -- initWithDisplayName:(NSString *) aDisplayName arguments:(NSArray *) args repository:(PBGitRepository *) repo; -@end diff --git a/Commands/PBStashCommand.m b/Commands/PBStashCommand.m deleted file mode 100644 index 53f9839..0000000 --- a/Commands/PBStashCommand.m +++ /dev/null @@ -1,44 +0,0 @@ -// -// PBStashCommand.m -// GitX -// -// Created by Tomasz Krasnyk on 10-11-06. -// Copyright 2010 __MyCompanyName__. All rights reserved. -// - -#import "PBStashCommand.h" -#import "PBRemoteProgressSheet.h" - -@interface PBStashCommand() -@property (nonatomic, retain) PBGitRepository *repository; -@property (nonatomic, retain) NSArray *arguments; -@end - - -@implementation PBStashCommand -@synthesize repository; -@synthesize arguments; - -- initWithDisplayName:(NSString *) aDisplayName arguments:(NSArray *) args repository:(PBGitRepository *) repo { - if (self = [super initWithDisplayName:aDisplayName parameters:[NSArray arrayWithObject:@"stash"]]) { - self.arguments = args; - self.repository = repo; - } - return self; -} - -- (void) dealloc { - [parameters release]; - [repository release]; - [super dealloc]; -} - - -- (void) invoke { - NSMutableArray *args = [[NSMutableArray alloc] initWithArray:super.parameters]; - [args addObjectsFromArray:self.arguments]; - [PBRemoteProgressSheet beginRemoteProgressSheetForArguments:args title:self.commandTitle description:self.commandDescription inRepository:self.repository]; - [args release]; -} - -@end diff --git a/Commands/PBStashCommandFactory.h b/Commands/PBStashCommandFactory.h index 291c47b..d4e0983 100644 --- a/Commands/PBStashCommandFactory.h +++ b/Commands/PBStashCommandFactory.h @@ -9,6 +9,7 @@ #import #import "PBCommandFactory.h" + @interface PBStashCommandFactory : NSObject { } diff --git a/Commands/PBStashCommandFactory.m b/Commands/PBStashCommandFactory.m index 83f8e0f..195cd7b 100644 --- a/Commands/PBStashCommandFactory.m +++ b/Commands/PBStashCommandFactory.m @@ -7,39 +7,81 @@ // #import "PBStashCommandFactory.h" -#import "PBStashCommand.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 { - if (![object isKindOfClass:[PBGitStash class]]) { - return nil; + 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]; } - PBGitStash *stash = (PBGitStash *) object; + + + return cmds; +} + ++ (NSArray *) commandsForRef:(PBGitRef *) ref repository:(PBGitRepository *) repository { NSMutableArray *commands = [[NSMutableArray alloc] init]; - NSArray *args = [NSArray arrayWithObjects:@"apply", [stash name], nil]; - PBStashCommand *command = [[PBStashCommand alloc] initWithDisplayName:@"Apply" arguments:args repository:repository]; + 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:@"pop", [stash name], nil]; - command = [[PBStashCommand alloc] initWithDisplayName:@"Pop" arguments:args repository:repository]; + 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:@"drop", [stash name], nil]; - command = [[PBStashCommand alloc] initWithDisplayName:@"Drop" arguments:args repository:repository]; + 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]; } 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/GitX.xcodeproj/project.pbxproj b/GitX.xcodeproj/project.pbxproj index 28ef783..3cf11aa 100644 --- a/GitX.xcodeproj/project.pbxproj +++ b/GitX.xcodeproj/project.pbxproj @@ -24,13 +24,22 @@ 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 */; }; - 21230CB11284B26A0046E5A1 /* PBGitSVStashItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 21230CB01284B26A0046E5A1 /* PBGitSVStashItem.m */; }; + 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 */; }; - 21230DEE12855A990046E5A1 /* PBStashCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 21230DED12855A990046E5A1 /* PBStashCommand.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 */; }; 3BC07F4C0ED5A5C5009A7768 /* HistoryViewTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = 3BC07F4A0ED5A5C5009A7768 /* HistoryViewTemplate.png */; }; 3BC07F4D0ED5A5C5009A7768 /* CommitViewTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = 3BC07F4B0ED5A5C5009A7768 /* CommitViewTemplate.png */; }; 47DBDB580E94EDE700671A1E /* DBPrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 47DBDB570E94EDE700671A1E /* DBPrefsWindowController.m */; }; @@ -252,8 +261,8 @@ 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 = ""; }; - 21230CAF1284B26A0046E5A1 /* PBGitSVStashItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitSVStashItem.h; sourceTree = ""; }; - 21230CB01284B26A0046E5A1 /* PBGitSVStashItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitSVStashItem.m; 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 = ""; }; @@ -265,8 +274,22 @@ 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 = ""; }; - 21230DEC12855A990046E5A1 /* PBStashCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBStashCommand.h; sourceTree = ""; }; - 21230DED12855A990046E5A1 /* PBStashCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBStashCommand.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 = ""; }; 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 = ""; }; @@ -549,6 +572,8 @@ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( + 21230EDF1285EF880046E5A1 /* Controller */, + 21230ED41285ED760046E5A1 /* View */, 21230D991285524C0046E5A1 /* Commands */, 21230D321284C4F10046E5A1 /* Model */, ); @@ -597,6 +622,8 @@ 21230D331284C5080046E5A1 /* PBGitStash.h */, 21230D341284C5080046E5A1 /* PBGitStash.m */, 21230D4D1284C92E0046E5A1 /* PBPresentable.h */, + 212311DB12872BF20046E5A1 /* PBGitSubmodule.h */, + 212311DC12872BF20046E5A1 /* PBGitSubmodule.m */, ); path = Model; sourceTree = ""; @@ -606,15 +633,37 @@ children = ( 21230D9A128552720046E5A1 /* PBCommand.h */, 21230D9B128552720046E5A1 /* PBCommand.m */, - 21230DEC12855A990046E5A1 /* PBStashCommand.h */, - 21230DED12855A990046E5A1 /* PBStashCommand.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 */, + ); + path = View; + sourceTree = ""; + }; + 21230EDF1285EF880046E5A1 /* Controller */ = { + isa = PBXGroup; + children = ( + 21230EE01285EFB20046E5A1 /* PBArgumentPickerController.h */, + 21230EE11285EFB20046E5A1 /* PBArgumentPickerController.m */, + ); + path = Controller; + sourceTree = ""; + }; 29B97314FDCFA39411CA2CEA /* GitTest */ = { isa = PBXGroup; children = ( @@ -642,6 +691,9 @@ 29B97315FDCFA39411CA2CEA /* Other Sources */ = { isa = PBXGroup; children = ( + 2123121B128735E90046E5A1 /* submodule-notmatching-index.png */, + 2123121C128735E90046E5A1 /* submodule-matching-index.png */, + 2123121D128735E90046E5A1 /* submodule-empty.png */, D858108011274D28007F254B /* Branch.png */, D858108111274D28007F254B /* RemoteBranch.png */, D858108211274D28007F254B /* Tag.png */, @@ -695,6 +747,7 @@ D8FDD9F511432A12005647F6 /* PBCloneRepositoryPanel.xib */, 47DBDB680E94EF6500671A1E /* Preferences.xib */, F569AE920F2CBD7C00C2FFA7 /* Credits.html */, + 21230ED11285EB5A0046E5A1 /* PBArgumentPicker.xib */, F58DB55F10566E3900CFDF4A /* PBGitSidebarView.xib */, D8022FE711E124A0003C21F6 /* PBGitXMessageSheet.xib */, ); @@ -793,8 +846,8 @@ D8FDDA63114335E8005647F6 /* PBGitSVRemoteBranchItem.m */, D8FDDA68114335E8005647F6 /* PBGitSVTagItem.h */, D8FDDA69114335E8005647F6 /* PBGitSVTagItem.m */, - 21230CAF1284B26A0046E5A1 /* PBGitSVStashItem.h */, - 21230CB01284B26A0046E5A1 /* PBGitSVStashItem.m */, + 21230CAF1284B26A0046E5A1 /* PBGitMenuItem.h */, + 21230CB01284B26A0046E5A1 /* PBGitMenuItem.m */, D8FDDA60114335E8005647F6 /* PBGitSVOtherRevItem.h */, D8FDDA61114335E8005647F6 /* PBGitSVOtherRevItem.m */, D8FDDA5E114335E8005647F6 /* PBGitSVFolderItem.h */, @@ -1242,6 +1295,10 @@ D8F4AB7912298CE200D6D53C /* rewindImage.pdf 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 */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1392,12 +1449,17 @@ D8B4DC571220D1E4004166D6 /* PBHistorySearchController.m in Sources */, D8712A00122B14EC00012334 /* GitXTextFieldCell.m in Sources */, 02B41A5E123E307200DFC531 /* PBCommitHookFailedSheet.m in Sources */, - 21230CB11284B26A0046E5A1 /* PBGitSVStashItem.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 */, - 21230DEE12855A990046E5A1 /* PBStashCommand.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 */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Model/PBGitStash.m b/Model/PBGitStash.m index e2f08c6..a042413 100644 --- a/Model/PBGitStash.m +++ b/Model/PBGitStash.m @@ -41,11 +41,15 @@ #pragma mark Presentable - (NSString *) displayDescription { - return self.name; + 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..3d99fcb --- /dev/null +++ b/Model/PBGitSubmodule.h @@ -0,0 +1,34 @@ +// +// 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; +} +@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; +@end diff --git a/Model/PBGitSubmodule.m b/Model/PBGitSubmodule.m new file mode 100644 index 0000000..0d71bb3 --- /dev/null +++ b/Model/PBGitSubmodule.m @@ -0,0 +1,113 @@ +// +// 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; + +- (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 { + [name release]; + [path release]; + [checkedOutCommit release]; + [super dealloc]; +} + +#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 index 299d208..4c6cf70 100644 --- a/Model/PBPresentable.h +++ b/Model/PBPresentable.h @@ -7,7 +7,8 @@ // -@protocol PBPresentable +@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/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/PBGitIndexController.m b/PBGitIndexController.m index d72e8bc..48d727c 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]; 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 986c0aa..85462fd 100644 --- a/PBGitRepository.h +++ b/PBGitRepository.h @@ -54,6 +54,7 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { PBGitSHA* _headSha; NSArray *stashes; + NSArray *submodules; } - (void) cloneRepositoryToPath:(NSString *)path bare:(BOOL)isBare; @@ -140,4 +141,6 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { @property (assign) PBGitRevSpecifier *currentBranch; @property (assign) NSInteger currentBranchFilter; @property (retain) NSMutableDictionary* refs; +@property (readonly) NSArray *stashes; +@property (readonly) NSArray *submodules; @end diff --git a/PBGitRepository.m b/PBGitRepository.m index 2d18d5d..23cc380 100644 --- a/PBGitRepository.m +++ b/PBGitRepository.m @@ -22,17 +22,20 @@ #import "PBHistorySearchController.h" #import "PBGitStash.h" +#import "PBGitSubmodule.h" NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; @interface PBGitRepository() @property (nonatomic, retain) NSArray *stashes; +@property (nonatomic, retain) NSArray *submodules; @end @implementation PBGitRepository @synthesize stashes; +@synthesize submodules; @synthesize revisionList, branches, currentBranch, refs, hasChanged, config; @synthesize currentBranchFilter; @@ -260,9 +263,11 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; NSString *output = [self outputInWorkdirForArguments:arguments]; NSArray *lines = [output componentsSeparatedByString:@"\n"]; - NSMutableArray *loadedStashes = [[NSMutableArray alloc] init]; + 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]; @@ -272,6 +277,23 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; [loadedStashes release]; } +- (void) reloadSubmodules { + + NSArray *arguments = [NSArray arrayWithObjects:@"submodule", @"status", @"--recursive", nil]; + NSString *output = [self 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]; + } + self.submodules = loadedSubmodules; +} + - (void) reloadRefs { _headRef = nil; @@ -307,6 +329,7 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; [self didChangeValueForKey:@"refs"]; [self reloadStashes]; + [self reloadSubmodules]; [[[self windowController] window] setTitle:[self displayName]]; } @@ -1166,11 +1189,6 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; return nil; } -- (void) dealloc { - [stashes release]; - [super dealloc]; -} - - (void) finalize { NSLog(@"Dealloc of repository"); diff --git a/PBGitSVStashItem.h b/PBGitSVStashItem.h deleted file mode 100644 index e3cd134..0000000 --- a/PBGitSVStashItem.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// PBGitSVStashItem.h -// GitX -// -// Created by Tomasz Krasnyk on 10-11-05. -// Copyright 2010 __MyCompanyName__. All rights reserved. -// - -#import -#import "PBSourceViewItem.h" -#import "PBGitStash.h" - - -@interface PBGitSVStashItem : PBSourceViewItem { - PBGitStash *stash; -} -@property (nonatomic, retain, readonly) PBGitStash *stash; - -- initWithStash:(PBGitStash *) aStash; -@end diff --git a/PBGitSVStashItem.m b/PBGitSVStashItem.m deleted file mode 100644 index d91d069..0000000 --- a/PBGitSVStashItem.m +++ /dev/null @@ -1,45 +0,0 @@ -// -// PBGitSVStashItem.m -// GitX -// -// Created by Tomasz Krasnyk on 10-11-05. -// Copyright 2010 __MyCompanyName__. All rights reserved. -// - -#import "PBGitSVStashItem.h" - - -@implementation PBGitSVStashItem -@synthesize stash; - -#pragma mark - -#pragma mark Inits/dealloc -//--------------------------------------------------------------------------------------------- - -- initWithStash:(PBGitStash *) aStash { - if (self = [super init]) { - NSString *displayTitle = [NSString stringWithFormat:@"%@ (%@)", [aStash message], [aStash stashSourceMessage]]; - super.title = displayTitle; - stash = [aStash retain]; - } - return self; -} - -- (void) dealloc { - [stash release]; - [super dealloc]; -} - -//--------------------------------------------------------------------------------------------- -#pragma mark - - - -- (NSImage *) icon { - static NSImage *tagImage = nil; - if (!tagImage) - tagImage = [NSImage imageNamed:@"stash-icon.png"]; - - return tagImage; -} - -@end diff --git a/PBGitSidebarController.h b/PBGitSidebarController.h index 68b5405..ad5967a 100644 --- a/PBGitSidebarController.h +++ b/PBGitSidebarController.h @@ -25,7 +25,7 @@ /* Specific things */ PBSourceViewItem *stage; - PBSourceViewItem *branches, *remotes, *tags, *others, *stashes; + PBSourceViewItem *branches, *remotes, *tags, *others, *stashes, *submodules; PBGitHistoryController *historyViewController; PBGitCommitController *commitViewController; diff --git a/PBGitSidebarController.m b/PBGitSidebarController.m index 81b696f..4a9c6ac 100644 --- a/PBGitSidebarController.m +++ b/PBGitSidebarController.m @@ -16,12 +16,16 @@ #import "PBAddRemoteSheet.h" #import "PBGitDefaults.h" #import "PBHistorySearchController.h" -#import "PBGitSVStashItem.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 () @@ -57,7 +61,9 @@ static NSString * const kObservingContextStashes = @"stashesChanged"; [repository addObserver:self forKeyPath:@"currentBranch" options:0 context:@"currentBranchChange"]; [repository addObserver:self forKeyPath:@"branches" options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew) context:@"branchesModified"]; - [repository addObserver:self forKeyPath:@"stashes" options:NSKeyValueObservingOptionNew context:@"stashesChanged"]; + [repository addObserver:self forKeyPath:@"stashes" options:NSKeyValueObservingOptionNew context:kObservingContextStashes]; + [repository addObserver:self forKeyPath:@"submodules" options:NSKeyValueObservingOptionNew context:kObservingContextSubmodules]; + [self menuNeedsUpdate:[actionButton menu]]; @@ -75,6 +81,7 @@ static NSString * const kObservingContextStashes = @"stashesChanged"; [repository removeObserver:self forKeyPath:@"currentBranch"]; [repository removeObserver:self forKeyPath:@"branches"]; [repository removeObserver:self forKeyPath:@"stashes"]; + [repository removeObserver:self forKeyPath:@"submodules"]; [super closeView]; } @@ -100,14 +107,39 @@ static NSString * const kObservingContextStashes = @"stashesChanged"; for (PBGitRevSpecifier *rev in removedRevSpecs) [self removeRevSpec:rev]; } - } else if ([@"stashesChanged" isEqualToString:context]) { // isEqualToString: is not needed here + } 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) { - PBGitSVStashItem *item = [[PBGitSVStashItem alloc] initWithStash:stash]; + 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 { @@ -268,6 +300,7 @@ static NSString * const kObservingContextStashes = @"stashesChanged"; 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]; @@ -278,12 +311,14 @@ static NSString * const kObservingContextStashes = @"stashesChanged"; [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]; } @@ -345,9 +380,11 @@ static NSString * const kObservingContextStashes = @"stashesChanged"; - (NSMenu *) menuForRow:(NSInteger)row { PBSourceViewItem *viewItem = [sourceView itemAtRow:row]; - if ([viewItem isKindOfClass:[PBGitSVStashItem class]]) { - PBGitSVStashItem *stashItem = (PBGitSVStashItem *) viewItem; - NSArray *commands = [PBStashCommandFactory commandsForObject:[stashItem stash] repository:historyViewController.repository]; + 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; } diff --git a/PBRefController.m b/PBRefController.m index c9b8c2e..2f8c00d 100644 --- a/PBRefController.m +++ b/PBRefController.m @@ -14,6 +14,8 @@ #import "PBGitDefaults.h" #import "PBDiffWindowController.h" +#import "PBArgumentPickerController.h" + @implementation PBRefController - (void)awakeFromNib @@ -212,7 +214,7 @@ } - (void) showTagInfoSheet:(PBRefMenuItem *)sender -{ +{ if ([[sender refish] refishType] != kGitXTagType) return; diff --git a/PBRefMenuItem.m b/PBRefMenuItem.m index 083de7b..a42b5be 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,11 +136,21 @@ [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]; } + + NSArray *cmds = [PBStashCommandFactory commandsForObject:ref repository:repo]; + if ([cmds count] > 0) { + for (PBCommand *cmd in cmds) { + PBCommandMenuItem *item = [[PBCommandMenuItem alloc] initWithCommand:cmd]; + [item setEnabled:YES]; + [items addObject:item]; + [item release]; + } + } return items; } 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/submodule-empty.png b/submodule-empty.png new file mode 100644 index 0000000000000000000000000000000000000000..c012e61103111827df4700f181fefba69fd18d08 GIT binary patch literal 3422 zcmV-k4WaUhP)Oz@Z0f2-7z;ux~O9+4z06=<WDR*FRcSTFz- zW=q650N5=6FiBTtNC2?60Km==3$g$R3;-}uh=nNt1bYBr$Ri_o0EC$U6h`t_Jn<{8 z5a%iY0C<_QJh>z}MS)ugEpZ1|S1ukX&Pf+56gFW3VVXcL!g-k)GJ!M?;PcD?0HBc- z5#WRK{dmp}uFlRjj{U%*%WZ25jX z{P*?XzTzZ-GF^d31o+^>%=Ap99M6&ogks$0k4OBs3;+Bb(;~!4V!2o<6ys46agIcq zjPo+3B8fthDa9qy|77CdEc*jK-!%ZRYCZvbku9iQV*~a}ClFY4z~c7+0P?$U!PF=S z1Au6Q;m>#f??3%Vpd|o+W=WE9003S@Bra6Svp>fO002awfhw>;8}z{#EWidF!3EsG z3;bXU&9EIRU@z1_9W=mEXoiz;4lcq~xDGvV5BgyU zp1~-*fe8db$Osc*A=-!mVv1NJjtCc-h4>-CNCXm#Bp}I%6j35eku^v$Qi@a{RY)E3 zJ#qp$hg?Rwkvqr$GJ^buyhkyVfwECO)C{#lxu`c9ghrwZ&}4KmnvWKso6vH!8a<3Q zq36)6Xb;+tK10Vaz~~qUGsJ8#F2=(`u{bOVlVi)VBCHIn#u~6ztOL7=^<&SmcLWlF zMZgI*1b0FpVIDz9SWH+>*hr`#93(Um+6gxa1B6k+CnA%mOSC4s5&6UzVlpv@SV$}* z))J2sFA#f(L&P^E5{W}HC%KRUNwK6<(h|}}(r!{C=`5+6G)NjFlgZj-YqAG9lq?`C z$c5yc>d>VnA`E_*3F2Qp##d8RZb=H01_mm@+|Cqnc9PsG(F5HIG_C zt)aG3uTh7n6Et<2In9F>NlT@zqLtGcXcuVrX|L#Xx)I%#9!{6gSJKPrN9dR61N3(c z4Tcqi$B1Vr8Jidf7-t!G7_XR2rWwr)$3XQ?}=hpK0&Z&W{| zep&sA23f;Q!%st`QJ}G3cbou<7-yIK2z4nfCCCtN2-XOGSWo##{8Q{ATurxr~;I`ytDs%xbip}RzP zziy}Qn4Z2~fSycmr`~zJ=lUFdFa1>gZThG6M+{g7vkW8#+YHVaJjFF}Z#*3@$J_By zLtVo_L#1JrVVB{Ak-5=4qt!-@Mh}c>#$4kh<88)m#-k<%CLtzEP3leVno>={htGUuD;o7bD)w_sX$S}eAxwzy?UvgBH(S?;#HZiQMoS*2K2 zT3xe7t(~nU*1N5{rxB;QPLocnp4Ml>u<^FZwyC!nu;thW+pe~4wtZn|Vi#w(#jeBd zlf9FDx_yoPJqHbk*$%56S{;6Kv~mM9!g3B(KJ}#RZ#@)!hR|78Dq|Iq-afF%KE1Brn_fm;Im z_u$xr8UFki1L{Ox>G0o)(&RAZ;=|I=wN2l97;cLaHH6leTB-XXa*h%dBOEvi`+x zi?=Txl?TadvyiL>SuF~-LZ;|cS}4~l2eM~nS7yJ>iOM;atDY;(?aZ^v+mJV$@1Ote z62cPUlD4IWOIIx&SmwQ~YB{nzae3Pc;}r!fhE@iwJh+OsDs9zItL;~pu715HdQEGA zUct(O!LkCy1<%NCg+}G`0PgpNm-?d@-hMgNe6^V+j6x$b<6@S<$+<4_1hi}Ti zncS4LsjI}fWY1>OX6feMEuLErma3QLmkw?X+1j)X-&VBk_4Y;EFPF_I+q;9dL%E~B zJh;4Nr^(LEJ3myURP{Rblsw%57T)g973R8o)DE9*xN#~;4_o$q%o z4K@u`jhx2fBXC4{U8Qn{*%*B$Ge=nny$HAYq{=vy|sI0 z_vss+H_qMky?OB#|JK!>IX&II^LlUh#rO5!7TtbwC;iULyV-Xq?ybB}ykGP{?LpZ? z-G|jbTmIbG@7#ZCz;~eY(cDM(28Dyq{*m>M4?_iynUBkc4TkHUI6gT!;y-fz>HMcd z&t%Ugo)`Y2{>!cx7B7DI)$7;J(U{Spm-3gBzioV_{p!H$8L!*M!p0uH$#^p{Ui4P` z?ZJ24cOCDe-w#jZd?0@)|7iKK^;6KN`;!@ylm7$*nDhK&GcDTy000JJOGiWi{{a60 z|De66lK=n!32;bRa{vGf6951U69E94oEQKA00(qQO+^RV3kMP@ItZSv1^@s8kV!;A zR5;6}lRIxDMHEKQt$qwMvty5Uy#b4`10X<#1Q4WTPDqeIh=hcgWYf*~2M7rfkob?V zE0#?V36B*4jKPdqt$W%t-OWrttLhT8ABdEyxXwNGeY&Em{GSs7eE!7|FTJ?8m#wmo zMC3Ju0}JFoWokjrI{GP zhydIck(Z4LK2Wc(7e)TzmBGVD->|>`?EalQ&v9#am+h?yaU5c;qw6f|^@g_XFkwi! zDLMXq_QHb)_u<}M3;+ssRS#FIoT4a*2Lo>J-bBQ(%5qNroKqBQ#Dr9JP1`inOG5+D zwGFD;1cAXAgCGES?@_NP3Ic&K1SSBqv0Zl^qIHhWc2re~2@FY+0FJV%XqpD^9d%uk zrU_Y|p{f@nE&#*Ph$xB%=4^4!`T3HwvxL$32Gi+H(lqIx{5u2dEQ)p_(ob}Kjp`L=9nLwtzo@l0 z@0@ej09D0WOI24?RZU&hbQd8himKwAWxXya{w`33An4`8*=!bm_2p-8eSQDo)@V4Q zvmHPE{1`C;3eGv4_cU!oSq?Bk0BD#bPkO*&v3L_W@ZO04JJTt9d(RU`Az5CKWjV`L z#&9^|#$-a4W&Ab&L#}oq&-2Y@vze%3K>Giq3TU2gYB2w||_~AOHXW07*qoM6N<$f_EQj Awg3PC literal 0 HcmV?d00001 diff --git a/submodule-matching-index.png b/submodule-matching-index.png new file mode 100644 index 0000000000000000000000000000000000000000..42d25baf3bcd6c322ea88ed3eb14df5fed78ea68 GIT binary patch literal 3505 zcmV;i4NmfjP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0008qNkl1v7&dkI!#zP=9Rw*F?R~2o_f`VEJ6-2KBAt69w&4Nm- z$|l?b68qc(EV>}5i3$=}Z4)a*EtyQ?hR97~J9aYm{GD@HG!R(xUBL6cdR~3PTFd`A z2jJW97TMe1e>IA>K9N#fky6e}Azv`ocuFaQ5T!BZz-YZ@p?Us%V=)ZF{hMEW{tR%~ z@8Kx9*m!;JgDlI*(hRLNLV#2Xr4(S#NFgt}p7){A`t9Lx@Xn0Ka3%y>?kD{1%`w8Lmle~HP z0#dm|@it38t?>BCF4FVq^$!^i29tlglK@4YVYJCy*THcdBm#i4DA1+GS_2YX<>0z5 zV6w6(P9>IFGfGEvy9am^9;>Ts2nzNOdK?Z0o3!2Twr~D4U6SJ4oY2Ottph0l%*!ibBxhwt;w>KJkQYD03ZZ_Ewt9B z0BbGdbVRq;rQ7Y&@AgTO5dg*-jIm_dm_K*h?Ci9$7Li}!)dizSAqF5&xI6%#%m33+<2c_ z)n_Yivl++y@hD>IrD@Kdn<3tc_<8w9A>_#laU3U|PN!xp5(IgkVXPqxL#ov(rqqm* zV_uv(gOn19L@McSw3<~QaTXR9R4+yHyp|xf^ z-sHDmS4c-kn}7!-!di% fz4h2yYyKJl{#$`)4H`~`00000NkvXXu0mjfs40rD literal 0 HcmV?d00001 diff --git a/submodule-notmatching-index.png b/submodule-notmatching-index.png new file mode 100644 index 0000000000000000000000000000000000000000..d5abd307c786055747cadd50ddb272a82d3e34cf GIT binary patch literal 425 zcmV;a0apHrP) Date: Thu, 25 Nov 2010 20:27:32 +0100 Subject: [PATCH 08/23] Commands can be now disabled --- Commands/PBCommand.h | 2 ++ Commands/PBCommand.m | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Commands/PBCommand.h b/Commands/PBCommand.h index 4f63935..8e3c1ae 100644 --- a/Commands/PBCommand.h +++ b/Commands/PBCommand.h @@ -19,7 +19,9 @@ 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; diff --git a/Commands/PBCommand.m b/Commands/PBCommand.m index e427372..a36364c 100644 --- a/Commands/PBCommand.m +++ b/Commands/PBCommand.m @@ -18,6 +18,7 @@ @synthesize commandDescription; @synthesize commandTitle; @synthesize repository; +@synthesize canBeFired; - (id) initWithDisplayName:(NSString *) aDisplayName parameters:(NSArray *) params { return [self initWithDisplayName:aDisplayName parameters:params repository:nil]; @@ -33,6 +34,7 @@ self.commandTitle = @""; self.commandDescription = @""; self.repository = repo; + self.canBeFired = YES; } return self; } From f38310365257b1692093f641c162b9579d5bbbcc Mon Sep 17 00:00:00 2001 From: Tomasz Krasnyk Date: Thu, 25 Nov 2010 20:28:15 +0100 Subject: [PATCH 09/23] Submodules can be updated/updated recursively --- Commands/PBRemoteCommandFactory.m | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Commands/PBRemoteCommandFactory.m b/Commands/PBRemoteCommandFactory.m index 934c6e3..2647bf9 100644 --- a/Commands/PBRemoteCommandFactory.m +++ b/Commands/PBRemoteCommandFactory.m @@ -17,14 +17,30 @@ NSMutableArray *commands = [[NSMutableArray alloc] init]; NSString *repoPath = [repository workingDirectory]; - NSString *path = [repoPath stringByAppendingPathComponent:[submodule path]]; + // open PBOpenDocumentCommand *command = [[PBOpenDocumentCommand alloc] initWithDocumentAbsolutePath:path]; command.commandTitle = command.displayName; command.commandDescription = @"Opening document"; + command.canBeFired = ([submodule path] && [submodule submoduleState] != PBGitSubmoduleStateNotInitialized); [commands addObject:command]; - + + // update + NSString *submodulePath = [submodule path]; + NSArray *params = [NSArray arrayWithObjects:@"submodule", @"update", nil]; + PBCommand *updateCmd = [[PBCommand alloc] initWithDisplayName:@"Update submodule" parameters:params repository:repository]; + updateCmd.commandTitle = updateCmd.displayName; + updateCmd.commandDescription = @"Updating submodule"; + [commands addObject:updateCmd]; + + // update recursively + NSArray *recursiveUpdate = [NSArray arrayWithObjects:@"submodule", @"update", @"--recursive", nil]; + PBCommand *updateRecursively = [[PBCommand alloc] initWithDisplayName:@"Update submodule recursively" parameters:recursiveUpdate repository:repository]; + updateRecursively.commandTitle = updateRecursively.displayName; + updateRecursively.commandDescription = [NSString stringWithFormat:@"Updating submodule %@ (recursively)", submodulePath]; + [commands addObject:updateRecursively]; + return commands; } From 17a4935f66513957e64ac83aecb3568bf74159ec Mon Sep 17 00:00:00 2001 From: Tomasz Krasnyk Date: Thu, 25 Nov 2010 20:35:37 +0100 Subject: [PATCH 10/23] OutlineView for the sidebar menu can be now tacked Commit on CMD+ENTER Added images for group items in sidebar menu --- GitX.xcodeproj/project.pbxproj | 56 ++- PBCommandMenuItem.m | 1 + PBGitCommitView.xib | 331 +++++++++++++++- PBGitSidebarController.m | 34 +- PBGitSidebarView.xib | 672 +++------------------------------ PBSourceViewCell.h | 8 +- PBSourceViewCell.m | 163 +++++++- PBSourceViewItem.h | 3 + PBSourceViewItem.m | 1 + View/CellTrackingRect.h | 64 ++++ View/TrackableOutlineView.h | 58 +++ View/TrackableOutlineView.m | 185 +++++++++ sourceListAction.png | Bin 0 -> 383 bytes sourceListActionOver.png | Bin 0 -> 344 bytes 14 files changed, 929 insertions(+), 647 deletions(-) create mode 100644 View/CellTrackingRect.h create mode 100644 View/TrackableOutlineView.h create mode 100644 View/TrackableOutlineView.m create mode 100644 sourceListAction.png create mode 100644 sourceListActionOver.png diff --git a/GitX.xcodeproj/project.pbxproj b/GitX.xcodeproj/project.pbxproj index 3cf11aa..0d028b1 100644 --- a/GitX.xcodeproj/project.pbxproj +++ b/GitX.xcodeproj/project.pbxproj @@ -24,6 +24,9 @@ 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 */; }; + 21025CA0129487AC00D87200 /* GTScaledButtonControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 21025C0B12947A6200D87200 /* GTScaledButtonControl.m */; }; 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 */; }; @@ -40,6 +43,14 @@ 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 */; }; + 21CF0AE3129C7BE00065B37C /* info-selected.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0ADD129C7BE00065B37C /* info-selected.tiff */; }; + 21CF0AE4129C7BE00065B37C /* info-selected-mouse.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0ADE129C7BE00065B37C /* info-selected-mouse.tiff */; }; + 21CF0AE5129C7BE00065B37C /* info-selected-hovered.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0ADF129C7BE00065B37C /* info-selected-hovered.tiff */; }; + 21CF0AE6129C7BE00065B37C /* info-normal.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0AE0129C7BE00065B37C /* info-normal.tiff */; }; + 21CF0AE7129C7BE00065B37C /* info-normal-mouse.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0AE1129C7BE00065B37C /* info-normal-mouse.tiff */; }; + 21CF0AE8129C7BE00065B37C /* info-normal-hovered.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0AE2129C7BE00065B37C /* info-normal-hovered.tiff */; }; + 21CF0B24129C7ED90065B37C /* TrackableOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 21CF0B23129C7ED90065B37C /* TrackableOutlineView.m */; }; + 21E331E4129DBFB100C3BA6F /* GTOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 21E331E3129DBFB100C3BA6F /* GTOutlineView.m */; }; 3BC07F4C0ED5A5C5009A7768 /* HistoryViewTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = 3BC07F4A0ED5A5C5009A7768 /* HistoryViewTemplate.png */; }; 3BC07F4D0ED5A5C5009A7768 /* CommitViewTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = 3BC07F4B0ED5A5C5009A7768 /* CommitViewTemplate.png */; }; 47DBDB580E94EDE700671A1E /* DBPrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 47DBDB570E94EDE700671A1E /* DBPrefsWindowController.m */; }; @@ -261,6 +272,11 @@ 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 = ""; }; + 21025C0A12947A6200D87200 /* GTScaledButtonControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTScaledButtonControl.h; sourceTree = ""; }; + 21025C0B12947A6200D87200 /* GTScaledButtonControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTScaledButtonControl.m; 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 = ""; }; + 21025CA6129487C200D87200 /* defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = defs.h; 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 = ""; }; @@ -290,6 +306,17 @@ 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 = ""; }; + 21CF0ADD129C7BE00065B37C /* info-selected.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-selected.tiff"; sourceTree = ""; }; + 21CF0ADE129C7BE00065B37C /* info-selected-mouse.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-selected-mouse.tiff"; sourceTree = ""; }; + 21CF0ADF129C7BE00065B37C /* info-selected-hovered.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-selected-hovered.tiff"; sourceTree = ""; }; + 21CF0AE0129C7BE00065B37C /* info-normal.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-normal.tiff"; sourceTree = ""; }; + 21CF0AE1129C7BE00065B37C /* info-normal-mouse.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-normal-mouse.tiff"; sourceTree = ""; }; + 21CF0AE2129C7BE00065B37C /* info-normal-hovered.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-normal-hovered.tiff"; 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 = ""; }; + 21E331E2129DBFB100C3BA6F /* GTOutlineView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTOutlineView.h; path = /Volumes/CORESYSTEMS/git/gitx/GTOutlineView.h; sourceTree = ""; }; + 21E331E3129DBFB100C3BA6F /* GTOutlineView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTOutlineView.m; path = /Volumes/CORESYSTEMS/git/gitx/GTOutlineView.m; 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 = ""; }; @@ -382,7 +409,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 = ""; }; @@ -649,8 +676,20 @@ 21230ED41285ED760046E5A1 /* View */ = { isa = PBXGroup; children = ( + 21CF0ADD129C7BE00065B37C /* info-selected.tiff */, + 21CF0ADE129C7BE00065B37C /* info-selected-mouse.tiff */, + 21CF0ADF129C7BE00065B37C /* info-selected-hovered.tiff */, + 21CF0AE0129C7BE00065B37C /* info-normal.tiff */, + 21CF0AE1129C7BE00065B37C /* info-normal-mouse.tiff */, + 21CF0AE2129C7BE00065B37C /* info-normal-hovered.tiff */, + 21025CA6129487C200D87200 /* defs.h */, + 21025C0A12947A6200D87200 /* GTScaledButtonControl.h */, + 21025C0B12947A6200D87200 /* GTScaledButtonControl.m */, 21230ED71285EDAF0046E5A1 /* PBArgumentPicker.h */, 21230ED81285EDAF0046E5A1 /* PBArgumentPicker.m */, + 21CF0B22129C7ED90065B37C /* TrackableOutlineView.h */, + 21CF0B23129C7ED90065B37C /* TrackableOutlineView.m */, + 21CF0B36129C80100065B37C /* CellTrackingRect.h */, ); path = View; sourceTree = ""; @@ -667,6 +706,8 @@ 29B97314FDCFA39411CA2CEA /* GitTest */ = { isa = PBXGroup; children = ( + 21E331E2129DBFB100C3BA6F /* GTOutlineView.h */, + 21E331E3129DBFB100C3BA6F /* GTOutlineView.m */, F5886A080ED5D26B0066E74C /* SpeedTest */, 913D5E420E5563FD00CECEA2 /* cli */, D89E9B4C1218C22A0097A90B /* GitXScripting */, @@ -726,6 +767,8 @@ 29B97317FDCFA39411CA2CEA /* Resources */ = { isa = PBXGroup; children = ( + 21025C1012947AB200D87200 /* sourceListAction.png */, + 21025C1112947AB200D87200 /* sourceListActionOver.png */, 02B41A5F123E307F00DFC531 /* PBCommitHookFailedSheet.xib */, F5F7D0641062E7940072C81C /* UpdateKey.pem */, F50A41130EBB872D00208746 /* Widgets */, @@ -1299,6 +1342,14 @@ 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 */, + 21CF0AE3129C7BE00065B37C /* info-selected.tiff in Resources */, + 21CF0AE4129C7BE00065B37C /* info-selected-mouse.tiff in Resources */, + 21CF0AE5129C7BE00065B37C /* info-selected-hovered.tiff in Resources */, + 21CF0AE6129C7BE00065B37C /* info-normal.tiff in Resources */, + 21CF0AE7129C7BE00065B37C /* info-normal-mouse.tiff in Resources */, + 21CF0AE8129C7BE00065B37C /* info-normal-hovered.tiff in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1460,6 +1511,9 @@ 212311DD12872BF20046E5A1 /* PBGitSubmodule.m in Sources */, 2123138A128756ED0046E5A1 /* PBRemoteCommandFactory.m in Sources */, 212313B5128759C00046E5A1 /* PBOpenDocumentCommand.m in Sources */, + 21025CA0129487AC00D87200 /* GTScaledButtonControl.m in Sources */, + 21CF0B24129C7ED90065B37C /* TrackableOutlineView.m in Sources */, + 21E331E4129DBFB100C3BA6F /* GTOutlineView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/PBCommandMenuItem.m b/PBCommandMenuItem.m index 3a080dd..50becd2 100644 --- a/PBCommandMenuItem.m +++ b/PBCommandMenuItem.m @@ -23,6 +23,7 @@ super.title = [aCommand displayName]; [self setTarget:aCommand]; [self setAction:@selector(invoke)]; + [self setEnabled:[aCommand canBeFired]]; } return self; } diff --git a/PBGitCommitView.xib b/PBGitCommitView.xib index 96cec64..b9bec40 100644 --- a/PBGitCommitView.xib +++ b/PBGitCommitView.xib @@ -2,10 +2,10 @@ 1050 - 10C540 - 762 - 1038.25 - 458.00 + 10F569 + 804 + 1038.29 + 461.00 YES @@ -15,13 +15,12 @@ YES - 762 - 762 + 804 + 804 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 @@ -365,8 +373,9 @@ public.url - {427, 41} + {{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,16 +715,19 @@ {{0, 190}, {852, 242}} + YES {852, 432} + CommitViewSplitView {852, 432} + NSView @@ -1360,7 +1387,7 @@ YES com.apple.InterfaceBuilder.CocoaPlugin - {{1091, 655}, {852, 432}} + {{393, 574}, {852, 432}} com.apple.InterfaceBuilder.CocoaPlugin @@ -1424,6 +1451,13 @@ YES + + NSApplication + + IBProjectSource + NSApplication+GitXScripting.h + + PBCommitMessageView NSTextView @@ -1448,6 +1482,7 @@ YES commit: + forceCommit: refresh: signOff: @@ -1456,6 +1491,36 @@ id id id + id + + + + YES + + YES + commit: + forceCommit: + refresh: + signOff: + + + YES + + commit: + id + + + forceCommit: + id + + + refresh: + id + + + signOff: + id + @@ -1479,6 +1544,45 @@ PBWebChangesController + + YES + + YES + cachedFilesController + commitButton + commitMessageView + indexController + unstagedFilesController + webController + + + YES + + cachedFilesController + NSArrayController + + + commitButton + NSButton + + + commitMessageView + NSTextView + + + indexController + PBGitIndexController + + + unstagedFilesController + NSArrayController + + + webController + PBWebChangesController + + + IBProjectSource PBGitCommitController.h @@ -1500,6 +1604,25 @@ NSTableView + + YES + + YES + rowClicked: + tableClicked: + + + YES + + rowClicked: + NSCell + + + tableClicked: + NSTableView + + + YES @@ -1519,6 +1642,40 @@ NSTableView + + YES + + YES + commitController + stagedFilesController + stagedTable + unstagedFilesController + unstagedTable + + + YES + + commitController + PBGitCommitController + + + stagedFilesController + NSArrayController + + + stagedTable + NSTableView + + + unstagedFilesController + NSArrayController + + + unstagedTable + NSTableView + + + IBProjectSource PBGitIndexController.h @@ -1547,6 +1704,13 @@ refresh: id + + refresh: + + refresh: + id + + IBProjectSource PBViewController.h @@ -1572,6 +1736,35 @@ NSArrayController + + YES + + YES + cachedFilesController + controller + indexController + unstagedFilesController + + + YES + + cachedFilesController + NSArrayController + + + controller + PBGitCommitController + + + indexController + PBGitIndexController + + + unstagedFilesController + NSArrayController + + + IBProjectSource PBWebChangesController.h @@ -1593,6 +1786,25 @@ WebView + + YES + + YES + repository + view + + + YES + + repository + id + + + view + WebView + + + IBProjectSource PBWebController.h @@ -1976,6 +2188,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 @@ -2185,6 +2425,13 @@ view NSView + + view + + view + NSView + + IBFrameworkSource AppKit.framework/Headers/NSViewController.h @@ -2224,6 +2471,70 @@ id + + YES + + YES + goBack: + goForward: + makeTextLarger: + makeTextSmaller: + makeTextStandardSize: + reload: + reloadFromOrigin: + stopLoading: + takeStringURLFrom: + toggleContinuousSpellChecking: + toggleSmartInsertDelete: + + + YES + + goBack: + id + + + goForward: + id + + + makeTextLarger: + id + + + makeTextSmaller: + id + + + makeTextStandardSize: + id + + + reload: + id + + + reloadFromOrigin: + id + + + stopLoading: + id + + + takeStringURLFrom: + id + + + toggleContinuousSpellChecking: + id + + + toggleSmartInsertDelete: + id + + + IBFrameworkSource WebKit.framework/Headers/WebView.h diff --git a/PBGitSidebarController.m b/PBGitSidebarController.m index 4a9c6ac..daa4337 100644 --- a/PBGitSidebarController.m +++ b/PBGitSidebarController.m @@ -269,7 +269,14 @@ static NSString * const kObservingContextSubmodules = @"submodulesChanged"; - (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(PBSourceViewCell *)cell forTableColumn:(NSTableColumn *)tableColumn item:(PBSourceViewItem *)item { cell.isCheckedOut = [item.revSpecifier isEqual:[repository headRef]]; - + BOOL showsActionButton = NO; + if ([item respondsToSelector:@selector(showsActionButton)]) { + showsActionButton = [item showsActionButton]; + [cell setTarget:self]; + cell.iInfoButtonAction = @selector(infoButtonAction:); + } + cell.showsActionButton = showsActionButton; + [cell setImage:[item icon]]; } @@ -278,6 +285,10 @@ static NSString * const kObservingContextSubmodules = @"submodulesChanged"; 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. @@ -295,12 +306,17 @@ static NSString * const kObservingContextSubmodules = @"submodulesChanged"; stage = [PBGitSVStageItem stageItem]; [project addChild:stage]; + branches = [PBSourceViewItem groupItemWithTitle:@"Branches"]; + branches.showsActionButton = YES; remotes = [PBSourceViewItem groupItemWithTitle:@"Remotes"]; + remotes.showsActionButton = YES; tags = [PBSourceViewItem groupItemWithTitle:@"Tags"]; others = [PBSourceViewItem groupItemWithTitle:@"Other"]; stashes = [PBSourceViewItem groupItemWithTitle:@"Stashes"]; + stashes.showsActionButton = YES; submodules = [PBSourceViewItem groupItemWithTitle:@"Submodules"]; + submodules.showsActionButton = YES; for (PBGitRevSpecifier *rev in repository.branches) [self addRevSpec:rev]; @@ -380,21 +396,25 @@ static NSString * const kObservingContextSubmodules = @"submodulesChanged"; - (NSMenu *) menuForRow:(NSInteger)row { PBSourceViewItem *viewItem = [sourceView itemAtRow:row]; - if ([viewItem isKindOfClass:[PBGitMenuItem class]]) { - PBGitMenuItem *stashItem = (PBGitMenuItem *) viewItem; + if ([viewItem isKindOfClass:[PBGitMenuItem class]] || [[viewItem title] isEqualToString:@"STASHES"]) { + PBGitMenuItem *stashItem = nil;//(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]; - [item setEnabled:YES]; [menu addItem:item]; [item release]; } + [menu addItem:[[NSMenuItem alloc] initWithTitle:@"hello" action:@selector(hello:) keyEquivalent:@""]]; + if ([[viewItem title] isEqualToString:@"STASHES"]){ + NSEvent *mouseEvent = [NSEvent mouseEventWithType:NSLeftMouseDown location:[NSEvent mouseLocation] modifierFlags:0 timestamp:[NSDate timeIntervalSinceReferenceDate] windowNumber:0 context:nil eventNumber:0 clickCount:1 pressure:0.1]; + NSPoint conv = [sourceView convertPoint:[mouseEvent locationInWindow] fromView:nil]; + [menu popUpMenuPositioningItem:nil atLocation:conv inView:sourceView]; + return nil; + } return menu; } diff --git a/PBGitSidebarView.xib b/PBGitSidebarView.xib index cdf65f9..463c28e 100644 --- a/PBGitSidebarView.xib +++ b/PBGitSidebarView.xib @@ -2,18 +2,24 @@ 1050 - 10C540 - 759 - 1038.25 - 458.00 - - com.apple.InterfaceBuilder.CocoaPlugin - 759 - - + 10F569 + 1222 + 1038.29 + YES - - + NSSegmentedControl + NSPopUpButton + NSScroller + NSMenuItem + NSMenu + NSTextFieldCell + NSScrollView + NSOutlineView + NSCustomView + NSCustomObject + NSPopUpButtonCell + NSTableColumn + NSSegmentedCell YES @@ -59,6 +65,8 @@ 4352 {153, 354} + + YES @@ -78,7 +86,7 @@ LucidaGrande 11 - 3100 + 3088 3 @@ -161,6 +169,7 @@ {153, 354} + @@ -171,6 +180,8 @@ -2147483392 {{137, 1}, {15, 338}} + + _doScroller: 0.99698790000000004 @@ -180,6 +191,8 @@ -2147483392 {{-100, -100}, {196, 15}} + + 1 _doScroller: @@ -188,7 +201,8 @@ {153, 354} - + + 528 @@ -198,10 +212,12 @@ {153, 354} + + NSView - + 268 YES @@ -281,7 +297,7 @@ LucidaGrande 13 - 1044 + 1040 -2034220801 @@ -354,12 +370,11 @@ {200, 31} - NSView - + YES @@ -592,6 +607,7 @@ YES -3.IBPluginDependency 10.IBPluginDependency + 11.CustomClassName 11.IBPluginDependency 13.IBPluginDependency 16.CustomClassName @@ -617,6 +633,7 @@ YES com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + TrackableOutlineView com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin PBSourceViewCell @@ -660,13 +677,6 @@ YES - - NSOutlineView - - IBProjectSource - NSOutlineViewExt.h - - PBGitSidebarController PBViewController @@ -695,7 +705,7 @@ IBProjectSource - PBGitSidebarController.h + ./classes-xjh84/PBGitSidebarController.h @@ -703,7 +713,7 @@ NSTextFieldCell IBProjectSource - PBIconAndTextCell.h + ./classes-xjh84/PBIconAndTextCell.h @@ -711,631 +721,47 @@ PBIconAndTextCell IBProjectSource - PBSourceViewCell.h + ./classes-xjh84/PBSourceViewCell.h PBViewController NSViewController + + refresh: + id + IBProjectSource - PBViewController.h + ./classes-xjh84/PBViewController.h - - - YES - NSActionCell - NSCell + TrackableOutlineView + NSOutlineView - 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 - - - - NSMenuItem - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenuItem.h - - - - NSMenuItemCell - NSButtonCell - - IBFrameworkSource - AppKit.framework/Headers/NSMenuItemCell.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 - 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 - - - - NSOutlineView - NSTableView - - - - NSPopUpButton - NSButton - - IBFrameworkSource - AppKit.framework/Headers/NSPopUpButton.h - - - - NSPopUpButtonCell - NSMenuItemCell - - IBFrameworkSource - AppKit.framework/Headers/NSPopUpButtonCell.h - - - - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSInterfaceStyle.h - - - - NSResponder - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSResponder.h - - - - NSScrollView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSScrollView.h - - - - NSScroller - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSScroller.h - - - - NSSegmentedCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSSegmentedCell.h - - - - NSSegmentedControl - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSSegmentedControl.h - - - - NSTableColumn - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableColumn.h - - - - NSTableView - NSControl - - - - NSTextFieldCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSTextFieldCell.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSClipView.h - - - - NSView - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSRulerView.h - - - - NSView - NSResponder - - - - NSViewController - NSResponder - - view - NSView - - - IBFrameworkSource - AppKit.framework/Headers/NSViewController.h - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSDrawer.h - - - - NSWindow - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSWindow.h - - - - NSWindow - - 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 YES GitX.xcodeproj 3 - - NSActionTemplate - {15, 15} - diff --git a/PBSourceViewCell.h b/PBSourceViewCell.h index 5b88392..f9ef694 100644 --- a/PBSourceViewCell.h +++ b/PBSourceViewCell.h @@ -12,8 +12,14 @@ @interface PBSourceViewCell : PBIconAndTextCell { BOOL isCheckedOut; + BOOL showsActionButton; + + BOOL iMouseDownInInfoButton; + BOOL iMouseHoveredInInfoButton; + SEL iInfoButtonAction; } - +@property (nonatomic) BOOL showsActionButton; +@property (nonatomic) SEL iInfoButtonAction; @property (assign) BOOL isCheckedOut; @end diff --git a/PBSourceViewCell.m b/PBSourceViewCell.m index eb60bca..cbc8576 100644 --- a/PBSourceViewCell.m +++ b/PBSourceViewCell.m @@ -9,23 +9,39 @@ #import "PBSourceViewCell.h" #import "PBGitSidebarController.h" #import "PBSourceViewBadge.h" +#import "GTScaledButtonControl.h" - +@interface PBSourceViewCell() +- (NSRect)infoButtonRectForBounds:(NSRect)bounds; +@end @implementation PBSourceViewCell - +@synthesize iInfoButtonAction; @synthesize isCheckedOut; +@synthesize showsActionButton; # 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]; + NSRect infoButtonRect = [self infoButtonRectForBounds:self.controlView.frame]; + if (showsActionButton && NSMouseInRect(point, infoButtonRect, [self.controlView isFlipped])){ + NSLog(@"elo elo"); + return nil; + } NSInteger row = [view rowAtPoint:point]; PBGitSidebarController *controller = [view delegate]; - + return [controller menuForRow:row]; } @@ -33,7 +49,7 @@ #pragma mark drawing - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)outlineView -{ +{ if (isCheckedOut) { NSImage *checkedOutImage = [PBSourceViewBadge checkedOutBadgeForCell:self]; NSSize imageSize = [checkedOutImage size]; @@ -52,4 +68,141 @@ [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]; + 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, 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. + + if (iMouseDownInInfoButton) { + // Send the action, and redisplay + iMouseDownInInfoButton = NO; + [controlView setNeedsDisplayInRect:cellFrame]; + NSLog(@"fired"); + if (iInfoButtonAction) { + [NSApp sendAction:iInfoButtonAction to:[self target] from:[self controlView]]; + } + } + + // 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 399f8e7..cf97d4b 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 5d450fb..aa756e0 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/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/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/sourceListAction.png b/sourceListAction.png new file mode 100644 index 0000000000000000000000000000000000000000..9122fc17e839be984b52e654a641d0a614a1c3cc GIT binary patch literal 383 zcmV-_0f7FAP)R6vxLK{Dr_l9rg&3rSDAtEfHX&Mq& zmL-Fg*wAr4f1vOCV>Lk#Mk9EhhZK8Mgi+TZ2(YeeAfJq}9}#pbiULWJ{I64QV;|I^nL$#Rh(qEPRcjR^PG-9U-q9J4 qtzzawshgp@*d#I0*&H-+7hnL4H? Date: Sat, 27 Nov 2010 17:25:27 +0100 Subject: [PATCH 11/23] History view shows file's icons --- PBGitHistoryController.m | 14 +++++++++ PBGitHistoryView.xib | 65 ++++++++++++++++++++++------------------ 2 files changed, 50 insertions(+), 29 deletions(-) diff --git a/PBGitHistoryController.m b/PBGitHistoryController.m index a8bf5ac..9d2ce3e 100644 --- a/PBGitHistoryController.m +++ b/PBGitHistoryController.m @@ -24,6 +24,7 @@ #define QLPreviewPanel NSClassFromString(@"QLPreviewPanel") #import "PBQLTextView.h" +#import "PBSourceViewCell.h" #define kHistorySelectedDetailIndexKey @"PBHistorySelectedDetailIndex" #define kHistoryDetailViewIndex 0 @@ -83,8 +84,10 @@ bottomColor:[NSColor colorWithCalibratedHue:0.579 saturation:0.119 brightness:0.765 alpha:1.000]]; //[scopeBarView setTopShade:207/255.0 bottomShade:180/255.0]; [self updateBranchFilterMatrix]; + [super awakeFromNib]; + [fileBrowser setDelegate:self]; } - (void)updateKeys @@ -755,4 +758,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 4bda4c9..735f2ff 100644 --- a/PBGitHistoryView.xib +++ b/PBGitHistoryView.xib @@ -3,7 +3,7 @@ 1050 10F569 - 788 + 823 1038.29 461.00 @@ -15,8 +15,8 @@ YES - 788 - 788 + 823 + 823 @@ -29,13 +29,8 @@ com.apple.WebKitIBPlugin - YES - - YES - - - YES - + PluginDependencyRecalculationVersion + YES @@ -517,7 +512,7 @@ - MMMM d, yyyy h:mm a + d MMMM yyyy HH:mm NO @@ -2159,7 +2154,9 @@ YES 0 - + + YES + @@ -2776,6 +2773,7 @@ 16.IBPluginDependency 17.IBPluginDependency 18.IBPluginDependency + 19.CustomClassName 19.IBPluginDependency 2.CustomClassName 2.IBEditorWindowLastContentRect @@ -2893,6 +2891,7 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + PBIconAndTextCell com.apple.InterfaceBuilder.CocoaPlugin PBCollapsibleSplitView {{312, 577}, {852, 384}} @@ -3127,6 +3126,13 @@ NSApplication+GitXScripting.h + + NSCell + + IBProjectSource + View/CellTrackingRect.h + + NSOutlineView @@ -3556,9 +3562,7 @@ YES YES - selectBasicSearch: - selectPickaxeSearch: - selectRegexSearch: + selectSearchMode: stepperPressed: updateSearch: @@ -3567,32 +3571,20 @@ id id id - id - id YES YES - selectBasicSearch: - selectPickaxeSearch: - selectRegexSearch: + selectSearchMode: stepperPressed: updateSearch: YES - selectBasicSearch: - id - - - selectPickaxeSearch: - id - - - selectRegexSearch: + selectSearchMode: id @@ -3670,6 +3662,14 @@ PBHistorySearchController.h + + PBIconAndTextCell + NSTextFieldCell + + IBProjectSource + PBIconAndTextCell.h + + PBNiceSplitView NSSplitView @@ -4464,6 +4464,13 @@ QuartzCore.framework/Headers/CIImageProvider.h + + NSObject + + IBFrameworkSource + ScriptingBridge.framework/Headers/SBApplication.h + + NSObject From 1fd08761d106c0d3af2935fc2cdc36667f56bbec Mon Sep 17 00:00:00 2001 From: Tomasz Krasnyk Date: Sat, 27 Nov 2010 17:25:57 +0100 Subject: [PATCH 12/23] Commented out unneeded code --- PBIconAndTextCell.m | 112 ++++++++++++++++++++-------------------- PBSourceViewCell.m | 122 ++++++++++++++++++++++++-------------------- 2 files changed, 122 insertions(+), 112 deletions(-) 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/PBSourceViewCell.m b/PBSourceViewCell.m index cbc8576..545df77 100644 --- a/PBSourceViewCell.m +++ b/PBSourceViewCell.m @@ -9,7 +9,6 @@ #import "PBSourceViewCell.h" #import "PBGitSidebarController.h" #import "PBSourceViewBadge.h" -#import "GTScaledButtonControl.h" @interface PBSourceViewCell() - (NSRect)infoButtonRectForBounds:(NSRect)bounds; @@ -33,11 +32,6 @@ - (NSMenu *) menuForEvent:(NSEvent *)event inRect:(NSRect)rect ofView:(NSOutlineView *)view { NSPoint point = [self.controlView convertPoint:[event locationInWindow] fromView:nil]; - NSRect infoButtonRect = [self infoButtonRectForBounds:self.controlView.frame]; - if (showsActionButton && NSMouseInRect(point, infoButtonRect, [self.controlView isFlipped])){ - NSLog(@"elo elo"); - return nil; - } NSInteger row = [view rowAtPoint:point]; PBGitSidebarController *controller = [view delegate]; @@ -99,51 +93,51 @@ } -- (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]; -} +//- (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; -} +//+ (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]; - +// [self setControlView:controlView]; +// NSRect infoButtonRect = [self infoButtonRectForBounds:cellFrame]; - while ([theEvent type] != NSLeftMouseUp) { + 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]); @@ -160,18 +154,34 @@ // 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 (iMouseDownInInfoButton) { - // Send the action, and redisplay - iMouseDownInInfoButton = NO; - [controlView setNeedsDisplayInRect:cellFrame]; - NSLog(@"fired"); - if (iInfoButtonAction) { - [NSApp sendAction:iInfoButtonAction to:[self target] from:[self controlView]]; + NSLog(@"mouse tracking; %@", theEvent); + 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]; } } - - // 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; + + if (iMouseDownInInfoButton) { + // Send the action, and redisplay + iMouseDownInInfoButton = NO; + [controlView setNeedsDisplayInRect:cellFrame]; + // NSLog(@"fired"); + // if (iInfoButtonAction) { + // [NSApp sendAction:iInfoButtonAction to:[self target] from:[self controlView]]; + // } + } + + 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; } From 40e3d8eb2ded68e26b3179f08ea0acf250d93675 Mon Sep 17 00:00:00 2001 From: Tomasz Krasnyk Date: Sun, 28 Nov 2010 00:38:32 +0100 Subject: [PATCH 13/23] commented unused code --- PBSourceViewCell.m | 5 ----- 1 file changed, 5 deletions(-) diff --git a/PBSourceViewCell.m b/PBSourceViewCell.m index 545df77..fa7a88a 100644 --- a/PBSourceViewCell.m +++ b/PBSourceViewCell.m @@ -154,7 +154,6 @@ // 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. - NSLog(@"mouse tracking; %@", theEvent); NSPoint locationOfTouch = [controlView convertPoint:[theEvent locationInWindow] fromView:nil]; BOOL mouseInButton = NSMouseInRect(locationOfTouch, [self infoButtonRectForBounds:cellFrame], [controlView isFlipped]); @@ -170,10 +169,6 @@ // Send the action, and redisplay iMouseDownInInfoButton = NO; [controlView setNeedsDisplayInRect:cellFrame]; - // NSLog(@"fired"); - // if (iInfoButtonAction) { - // [NSApp sendAction:iInfoButtonAction to:[self target] from:[self controlView]]; - // } } return [super trackMouse:theEvent inRect:cellFrame ofView:controlView untilMouseUp:flag]; From f12187338ed8db8b8a78867c2a37cd4ba17b2941 Mon Sep 17 00:00:00 2001 From: Tomasz Krasnyk Date: Sun, 28 Nov 2010 00:38:52 +0100 Subject: [PATCH 14/23] submodules are now nested --- Model/PBGitSubmodule.h | 5 +++++ Model/PBGitSubmodule.m | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/Model/PBGitSubmodule.h b/Model/PBGitSubmodule.h index 3d99fcb..5d1db18 100644 --- a/Model/PBGitSubmodule.h +++ b/Model/PBGitSubmodule.h @@ -21,7 +21,10 @@ typedef enum { 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; @@ -31,4 +34,6 @@ typedef enum { + (NSImage *) imageForSubmoduleState:(PBGitSubmoduleState) state; + (PBGitSubmoduleState) submoduleStateFromCharacter:(unichar) character; + +- (void) addSubmodule:(PBGitSubmodule *) submodule; @end diff --git a/Model/PBGitSubmodule.m b/Model/PBGitSubmodule.m index 0d71bb3..cea00d0 100644 --- a/Model/PBGitSubmodule.m +++ b/Model/PBGitSubmodule.m @@ -20,6 +20,14 @@ @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); @@ -51,12 +59,17 @@ } - (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 From be507c82303f47aaa4da89867408c96ca4e2c1ce Mon Sep 17 00:00:00 2001 From: Tomasz Krasnyk Date: Sun, 28 Nov 2010 00:41:27 +0100 Subject: [PATCH 15/23] - Added controller 4 stashes, submodules, reset management - Added additional menu for the repository actions - Added action for 'Revealing in Finder' --- Commands/PBRevealWithFinderCommand.h | 17 ++++ Commands/PBRevealWithFinderCommand.m | 31 +++++++ Controller/PBGitResetController.h | 24 +++++ Controller/PBGitResetController.m | 60 ++++++++++++ Controller/PBSubmoduleController.h | 37 ++++++++ Controller/PBSubmoduleController.m | 133 +++++++++++++++++++++++++++ GitX.xcodeproj/project.pbxproj | 60 +++++------- PBGitRepository.h | 16 +++- PBGitRepository.m | 68 ++++++-------- PBGitSidebarController.m | 28 +++--- PBStashController.h | 31 +++++++ PBStashController.m | 110 ++++++++++++++++++++++ 12 files changed, 516 insertions(+), 99 deletions(-) create mode 100644 Commands/PBRevealWithFinderCommand.h create mode 100644 Commands/PBRevealWithFinderCommand.m create mode 100644 Controller/PBGitResetController.h create mode 100644 Controller/PBGitResetController.m create mode 100644 Controller/PBSubmoduleController.h create mode 100644 Controller/PBSubmoduleController.m create mode 100644 PBStashController.h create mode 100644 PBStashController.m 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/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..f0d199a --- /dev/null +++ b/Controller/PBGitResetController.m @@ -0,0 +1,60 @@ +// +// 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" + +@implementation PBGitResetController + +- (id) initWithRepository:(PBGitRepository *) repo { + if (self = [super init]){ + repository = [repo retain]; + } + return self; +} + +- (void) resetHardToHead { + 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"; + [cmd invoke]; +} + +- (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]; +} + + +@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/GitX.xcodeproj/project.pbxproj b/GitX.xcodeproj/project.pbxproj index 0d028b1..3d0cd83 100644 --- a/GitX.xcodeproj/project.pbxproj +++ b/GitX.xcodeproj/project.pbxproj @@ -26,7 +26,6 @@ 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 */; }; - 21025CA0129487AC00D87200 /* GTScaledButtonControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 21025C0B12947A6200D87200 /* GTScaledButtonControl.m */; }; 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 */; }; @@ -43,14 +42,11 @@ 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 */; }; - 21CF0AE3129C7BE00065B37C /* info-selected.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0ADD129C7BE00065B37C /* info-selected.tiff */; }; - 21CF0AE4129C7BE00065B37C /* info-selected-mouse.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0ADE129C7BE00065B37C /* info-selected-mouse.tiff */; }; - 21CF0AE5129C7BE00065B37C /* info-selected-hovered.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0ADF129C7BE00065B37C /* info-selected-hovered.tiff */; }; - 21CF0AE6129C7BE00065B37C /* info-normal.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0AE0129C7BE00065B37C /* info-normal.tiff */; }; - 21CF0AE7129C7BE00065B37C /* info-normal-mouse.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0AE1129C7BE00065B37C /* info-normal-mouse.tiff */; }; - 21CF0AE8129C7BE00065B37C /* info-normal-hovered.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0AE2129C7BE00065B37C /* info-normal-hovered.tiff */; }; + 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 */; }; - 21E331E4129DBFB100C3BA6F /* GTOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 21E331E3129DBFB100C3BA6F /* GTOutlineView.m */; }; 3BC07F4C0ED5A5C5009A7768 /* HistoryViewTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = 3BC07F4A0ED5A5C5009A7768 /* HistoryViewTemplate.png */; }; 3BC07F4D0ED5A5C5009A7768 /* CommitViewTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = 3BC07F4B0ED5A5C5009A7768 /* CommitViewTemplate.png */; }; 47DBDB580E94EDE700671A1E /* DBPrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 47DBDB570E94EDE700671A1E /* DBPrefsWindowController.m */; }; @@ -272,8 +268,6 @@ 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 = ""; }; - 21025C0A12947A6200D87200 /* GTScaledButtonControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTScaledButtonControl.h; sourceTree = ""; }; - 21025C0B12947A6200D87200 /* GTScaledButtonControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTScaledButtonControl.m; 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 = ""; }; 21025CA6129487C200D87200 /* defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = defs.h; sourceTree = ""; }; @@ -306,17 +300,17 @@ 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 = ""; }; - 21CF0ADD129C7BE00065B37C /* info-selected.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-selected.tiff"; sourceTree = ""; }; - 21CF0ADE129C7BE00065B37C /* info-selected-mouse.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-selected-mouse.tiff"; sourceTree = ""; }; - 21CF0ADF129C7BE00065B37C /* info-selected-hovered.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-selected-hovered.tiff"; sourceTree = ""; }; - 21CF0AE0129C7BE00065B37C /* info-normal.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-normal.tiff"; sourceTree = ""; }; - 21CF0AE1129C7BE00065B37C /* info-normal-mouse.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-normal-mouse.tiff"; sourceTree = ""; }; - 21CF0AE2129C7BE00065B37C /* info-normal-hovered.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-normal-hovered.tiff"; 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 = ""; }; - 21E331E2129DBFB100C3BA6F /* GTOutlineView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTOutlineView.h; path = /Volumes/CORESYSTEMS/git/gitx/GTOutlineView.h; sourceTree = ""; }; - 21E331E3129DBFB100C3BA6F /* GTOutlineView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTOutlineView.m; path = /Volumes/CORESYSTEMS/git/gitx/GTOutlineView.m; 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 = ""; }; @@ -658,6 +652,8 @@ 21230D991285524C0046E5A1 /* Commands */ = { isa = PBXGroup; children = ( + 217FF0BC12A1CB3E00785A65 /* PBRevealWithFinderCommand.m */, + 217FF0BD12A1CB3E00785A65 /* PBRevealWithFinderCommand.h */, 21230D9A128552720046E5A1 /* PBCommand.h */, 21230D9B128552720046E5A1 /* PBCommand.m */, 21230D9D128552FA0046E5A1 /* PBStashCommandFactory.h */, @@ -676,15 +672,7 @@ 21230ED41285ED760046E5A1 /* View */ = { isa = PBXGroup; children = ( - 21CF0ADD129C7BE00065B37C /* info-selected.tiff */, - 21CF0ADE129C7BE00065B37C /* info-selected-mouse.tiff */, - 21CF0ADF129C7BE00065B37C /* info-selected-hovered.tiff */, - 21CF0AE0129C7BE00065B37C /* info-normal.tiff */, - 21CF0AE1129C7BE00065B37C /* info-normal-mouse.tiff */, - 21CF0AE2129C7BE00065B37C /* info-normal-hovered.tiff */, 21025CA6129487C200D87200 /* defs.h */, - 21025C0A12947A6200D87200 /* GTScaledButtonControl.h */, - 21025C0B12947A6200D87200 /* GTScaledButtonControl.m */, 21230ED71285EDAF0046E5A1 /* PBArgumentPicker.h */, 21230ED81285EDAF0046E5A1 /* PBArgumentPicker.m */, 21CF0B22129C7ED90065B37C /* TrackableOutlineView.h */, @@ -697,6 +685,12 @@ 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 */, ); @@ -706,8 +700,6 @@ 29B97314FDCFA39411CA2CEA /* GitTest */ = { isa = PBXGroup; children = ( - 21E331E2129DBFB100C3BA6F /* GTOutlineView.h */, - 21E331E3129DBFB100C3BA6F /* GTOutlineView.m */, F5886A080ED5D26B0066E74C /* SpeedTest */, 913D5E420E5563FD00CECEA2 /* cli */, D89E9B4C1218C22A0097A90B /* GitXScripting */, @@ -1344,12 +1336,6 @@ 21231220128735E90046E5A1 /* submodule-empty.png in Resources */, 21025C1212947AB200D87200 /* sourceListAction.png in Resources */, 21025C1312947AB200D87200 /* sourceListActionOver.png in Resources */, - 21CF0AE3129C7BE00065B37C /* info-selected.tiff in Resources */, - 21CF0AE4129C7BE00065B37C /* info-selected-mouse.tiff in Resources */, - 21CF0AE5129C7BE00065B37C /* info-selected-hovered.tiff in Resources */, - 21CF0AE6129C7BE00065B37C /* info-normal.tiff in Resources */, - 21CF0AE7129C7BE00065B37C /* info-normal-mouse.tiff in Resources */, - 21CF0AE8129C7BE00065B37C /* info-normal-hovered.tiff in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1511,9 +1497,11 @@ 212311DD12872BF20046E5A1 /* PBGitSubmodule.m in Sources */, 2123138A128756ED0046E5A1 /* PBRemoteCommandFactory.m in Sources */, 212313B5128759C00046E5A1 /* PBOpenDocumentCommand.m in Sources */, - 21025CA0129487AC00D87200 /* GTScaledButtonControl.m in Sources */, 21CF0B24129C7ED90065B37C /* TrackableOutlineView.m in Sources */, - 21E331E4129DBFB100C3BA6F /* GTOutlineView.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; }; diff --git a/PBGitRepository.h b/PBGitRepository.h index 85462fd..aeef8df 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, @@ -53,9 +57,13 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { PBGitRevSpecifier *_headRef; // Caching PBGitSHA* _headSha; - NSArray *stashes; - NSArray *submodules; + 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; @@ -93,7 +101,6 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { - (NSString *)gitIgnoreFilename; - (BOOL)isBareRepository; -- (void) reloadStashes; - (void) reloadRefs; - (void) addRef:(PBGitRef *)ref fromParameters:(NSArray *)params; - (void) lazyReload; @@ -132,6 +139,7 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { // for the scripting bridge - (void)findInModeScriptCommand:(NSScriptCommand *)command; +- (NSMenu *) menu; @property (assign) BOOL hasChanged; @property (readonly) PBGitWindowController *windowController; @@ -141,6 +149,4 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { @property (assign) PBGitRevSpecifier *currentBranch; @property (assign) NSInteger currentBranchFilter; @property (retain) NSMutableDictionary* refs; -@property (readonly) NSArray *stashes; -@property (readonly) NSArray *submodules; @end diff --git a/PBGitRepository.m b/PBGitRepository.m index 23cc380..d8f7ea4 100644 --- a/PBGitRepository.m +++ b/PBGitRepository.m @@ -27,18 +27,34 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; @interface PBGitRepository() -@property (nonatomic, retain) NSArray *stashes; -@property (nonatomic, retain) NSArray *submodules; @end @implementation PBGitRepository -@synthesize stashes; -@synthesize submodules; +@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) { @@ -146,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 @@ -258,42 +278,6 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; [refs setObject:[NSMutableArray arrayWithObject:ref] forKey:sha]; } -- (void) reloadStashes { - NSArray *arguments = [NSArray arrayWithObjects:@"stash", @"list", nil]; - NSString *output = [self 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]; -} - -- (void) reloadSubmodules { - - NSArray *arguments = [NSArray arrayWithObjects:@"submodule", @"status", @"--recursive", nil]; - NSString *output = [self 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]; - } - self.submodules = loadedSubmodules; -} - - (void) reloadRefs { _headRef = nil; @@ -328,8 +312,8 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; [self willChangeValueForKey:@"refs"]; [self didChangeValueForKey:@"refs"]; - [self reloadStashes]; - [self reloadSubmodules]; + [self.stashController reload]; + [self.submoduleController reload]; [[[self windowController] window] setTitle:[self displayName]]; } diff --git a/PBGitSidebarController.m b/PBGitSidebarController.m index daa4337..87f7a7a 100644 --- a/PBGitSidebarController.m +++ b/PBGitSidebarController.m @@ -61,8 +61,8 @@ static NSString * const kObservingContextSubmodules = @"submodulesChanged"; [repository addObserver:self forKeyPath:@"currentBranch" options:0 context:@"currentBranchChange"]; [repository addObserver:self forKeyPath:@"branches" options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew) context:@"branchesModified"]; - [repository addObserver:self forKeyPath:@"stashes" options:NSKeyValueObservingOptionNew context:kObservingContextStashes]; - [repository addObserver:self forKeyPath:@"submodules" options:NSKeyValueObservingOptionNew context:kObservingContextSubmodules]; + [repository addObserver:self forKeyPath:@"stashController.stashes" options:NSKeyValueObservingOptionNew context:kObservingContextStashes]; + [repository addObserver:self forKeyPath:@"submoduleController.submodules" options:NSKeyValueObservingOptionNew context:kObservingContextSubmodules]; [self menuNeedsUpdate:[actionButton menu]]; @@ -80,8 +80,8 @@ static NSString * const kObservingContextSubmodules = @"submodulesChanged"; [repository removeObserver:self forKeyPath:@"currentBranch"]; [repository removeObserver:self forKeyPath:@"branches"]; - [repository removeObserver:self forKeyPath:@"stashes"]; - [repository removeObserver:self forKeyPath:@"submodules"]; + [repository removeObserver:self forKeyPath:@"stashController.stashes"]; + [repository removeObserver:self forKeyPath:@"submoduleController.submodules"]; [super closeView]; } @@ -301,6 +301,7 @@ static NSString * const kObservingContextSubmodules = @"submodulesChanged"; - (void)populateList { PBSourceViewItem *project = [PBSourceViewItem groupItemWithTitle:[repository projectName]]; + project.showsActionButton = YES; project.isUncollapsible = YES; stage = [PBGitSVStageItem stageItem]; @@ -308,15 +309,11 @@ static NSString * const kObservingContextSubmodules = @"submodulesChanged"; branches = [PBSourceViewItem groupItemWithTitle:@"Branches"]; - branches.showsActionButton = YES; remotes = [PBSourceViewItem groupItemWithTitle:@"Remotes"]; - remotes.showsActionButton = YES; tags = [PBSourceViewItem groupItemWithTitle:@"Tags"]; others = [PBSourceViewItem groupItemWithTitle:@"Other"]; stashes = [PBSourceViewItem groupItemWithTitle:@"Stashes"]; - stashes.showsActionButton = YES; submodules = [PBSourceViewItem groupItemWithTitle:@"Submodules"]; - submodules.showsActionButton = YES; for (PBGitRevSpecifier *rev in repository.branches) [self addRevSpec:rev]; @@ -395,12 +392,18 @@ static NSString * const kObservingContextSubmodules = @"submodulesChanged"; - (NSMenu *) menuForRow:(NSInteger)row { + if (row == 0) { + return [historyViewController.repository menu]; + } PBSourceViewItem *viewItem = [sourceView itemAtRow:row]; if ([viewItem isKindOfClass:[PBGitMenuItem class]] || [[viewItem title] isEqualToString:@"STASHES"]) { - PBGitMenuItem *stashItem = nil;//(PBGitMenuItem *) viewItem; + 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) { @@ -408,13 +411,6 @@ static NSString * const kObservingContextSubmodules = @"submodulesChanged"; [menu addItem:item]; [item release]; } - [menu addItem:[[NSMenuItem alloc] initWithTitle:@"hello" action:@selector(hello:) keyEquivalent:@""]]; - if ([[viewItem title] isEqualToString:@"STASHES"]){ - NSEvent *mouseEvent = [NSEvent mouseEventWithType:NSLeftMouseDown location:[NSEvent mouseLocation] modifierFlags:0 timestamp:[NSDate timeIntervalSinceReferenceDate] windowNumber:0 context:nil eventNumber:0 clickCount:1 pressure:0.1]; - NSPoint conv = [sourceView convertPoint:[mouseEvent locationInWindow] fromView:nil]; - [menu popUpMenuPositioningItem:nil atLocation:conv inView:sourceView]; - return nil; - } return menu; } 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 From e3ed9ad9b04a9ccb601af85f175df0a34339babd Mon Sep 17 00:00:00 2001 From: Tomasz Krasnyk Date: Sun, 28 Nov 2010 21:05:41 +0100 Subject: [PATCH 16/23] Added double click action on a module --- PBGitSidebarController.m | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/PBGitSidebarController.m b/PBGitSidebarController.m index 87f7a7a..171359a 100644 --- a/PBGitSidebarController.m +++ b/PBGitSidebarController.m @@ -71,6 +71,9 @@ static NSString * const kObservingContextSubmodules = @"submodulesChanged"; [self selectStage]; else [self selectCurrentBranch]; + + [sourceView setDoubleAction:@selector(outlineDoubleClicked)]; + [sourceView setTarget:self]; } - (void)closeView @@ -190,6 +193,17 @@ static NSString * const kObservingContextSubmodules = @"submodulesChanged"; [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; @@ -396,7 +410,7 @@ static NSString * const kObservingContextSubmodules = @"submodulesChanged"; return [historyViewController.repository menu]; } PBSourceViewItem *viewItem = [sourceView itemAtRow:row]; - if ([viewItem isKindOfClass:[PBGitMenuItem class]] || [[viewItem title] isEqualToString:@"STASHES"]) { + if ([viewItem isKindOfClass:[PBGitMenuItem class]]) { PBGitMenuItem *stashItem = (PBGitMenuItem *) viewItem; NSMutableArray *commands = [[NSMutableArray alloc] init]; [commands addObjectsFromArray:[PBStashCommandFactory commandsForObject:[stashItem sourceObject] repository:historyViewController.repository]]; From 81bb83a0da02f91799ef288aafd1b48290dd8f82 Mon Sep 17 00:00:00 2001 From: Tomasz Krasnyk Date: Sun, 28 Nov 2010 21:06:09 +0100 Subject: [PATCH 17/23] Showing submodule actions only when possible --- Commands/PBRemoteCommandFactory.m | 33 +++++++++++++++++-------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/Commands/PBRemoteCommandFactory.m b/Commands/PBRemoteCommandFactory.m index 2647bf9..d1baa83 100644 --- a/Commands/PBRemoteCommandFactory.m +++ b/Commands/PBRemoteCommandFactory.m @@ -19,27 +19,30 @@ NSString *repoPath = [repository workingDirectory]; NSString *path = [repoPath stringByAppendingPathComponent:[submodule path]]; - // open - PBOpenDocumentCommand *command = [[PBOpenDocumentCommand alloc] initWithDocumentAbsolutePath:path]; - command.commandTitle = command.displayName; - command.commandDescription = @"Opening document"; - command.canBeFired = ([submodule path] && [submodule submoduleState] != PBGitSubmoduleStateNotInitialized); - [commands addObject:command]; + if ([submodule submoduleState] != PBGitSubmoduleStateNotInitialized) { + // open + PBOpenDocumentCommand *command = [[PBOpenDocumentCommand alloc] initWithDocumentAbsolutePath:path]; + command.commandTitle = command.displayName; + command.commandDescription = @"Opening document"; + [commands addObject:command]; + } // update NSString *submodulePath = [submodule path]; - NSArray *params = [NSArray arrayWithObjects:@"submodule", @"update", nil]; - PBCommand *updateCmd = [[PBCommand alloc] initWithDisplayName:@"Update submodule" parameters:params repository:repository]; + NSArray *params = [NSArray arrayWithObjects:@"submodule", @"update", submodulePath, nil]; + PBCommand *updateCmd = [[PBCommand alloc] initWithDisplayName:@"Update" parameters:params repository:repository]; updateCmd.commandTitle = updateCmd.displayName; - updateCmd.commandDescription = @"Updating submodule"; + updateCmd.commandDescription = [NSString stringWithFormat:@"Updating submodule %@", submodulePath]; [commands addObject:updateCmd]; - // update recursively - NSArray *recursiveUpdate = [NSArray arrayWithObjects:@"submodule", @"update", @"--recursive", nil]; - PBCommand *updateRecursively = [[PBCommand alloc] initWithDisplayName:@"Update submodule recursively" parameters:recursiveUpdate repository:repository]; - updateRecursively.commandTitle = updateRecursively.displayName; - updateRecursively.commandDescription = [NSString stringWithFormat:@"Updating submodule %@ (recursively)", submodulePath]; - [commands addObject:updateRecursively]; + 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]; + } return commands; } From b948127cc2e3a3df084c0887581d3dec24968011 Mon Sep 17 00:00:00 2001 From: Tomasz Krasnyk Date: Sun, 28 Nov 2010 21:13:43 +0100 Subject: [PATCH 18/23] Added command for initializing submodules --- Commands/PBRemoteCommandFactory.m | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Commands/PBRemoteCommandFactory.m b/Commands/PBRemoteCommandFactory.m index d1baa83..29b1494 100644 --- a/Commands/PBRemoteCommandFactory.m +++ b/Commands/PBRemoteCommandFactory.m @@ -18,6 +18,7 @@ NSString *repoPath = [repository workingDirectory]; NSString *path = [repoPath stringByAppendingPathComponent:[submodule path]]; + NSString *submodulePath = [submodule path]; if ([submodule submoduleState] != PBGitSubmoduleStateNotInitialized) { // open @@ -27,8 +28,15 @@ [commands addObject:command]; } + 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 - NSString *submodulePath = [submodule path]; NSArray *params = [NSArray arrayWithObjects:@"submodule", @"update", submodulePath, nil]; PBCommand *updateCmd = [[PBCommand alloc] initWithDisplayName:@"Update" parameters:params repository:repository]; updateCmd.commandTitle = updateCmd.displayName; From 71e9e2cc43b449c8a04dbaa4118c9ed78968ddb8 Mon Sep 17 00:00:00 2001 From: Tomasz Krasnyk Date: Sun, 28 Nov 2010 21:16:19 +0100 Subject: [PATCH 19/23] Added action to reveal submodule path --- Commands/PBRemoteCommandFactory.m | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Commands/PBRemoteCommandFactory.m b/Commands/PBRemoteCommandFactory.m index 29b1494..2b02524 100644 --- a/Commands/PBRemoteCommandFactory.m +++ b/Commands/PBRemoteCommandFactory.m @@ -9,6 +9,7 @@ #import "PBRemoteCommandFactory.h" #import "PBOpenDocumentCommand.h" #import "PBGitSubmodule.h" +#import "PBRevealWithFinderCommand.h" @implementation PBRemoteCommandFactory @@ -20,14 +21,6 @@ NSString *path = [repoPath stringByAppendingPathComponent:[submodule path]]; NSString *submodulePath = [submodule path]; - if ([submodule submoduleState] != PBGitSubmoduleStateNotInitialized) { - // open - PBOpenDocumentCommand *command = [[PBOpenDocumentCommand alloc] initWithDocumentAbsolutePath:path]; - command.commandTitle = command.displayName; - command.commandDescription = @"Opening document"; - [commands addObject:command]; - } - if ([submodule submoduleState] == PBGitSubmoduleStateNotInitialized) { NSArray *params = [NSArray arrayWithObjects:@"submodule", @"init", submodulePath, nil]; PBCommand *initCmd = [[PBCommand alloc] initWithDisplayName:@"Init" parameters:params repository:repository]; @@ -52,6 +45,16 @@ [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; } From 27e490c405710ddac30f51cab7e1098d2bfe34df Mon Sep 17 00:00:00 2001 From: Tomasz Krasnyk Date: Sun, 28 Nov 2010 22:51:47 +0100 Subject: [PATCH 20/23] Reset now asks user for confirmation --- Controller/PBGitResetController.m | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/Controller/PBGitResetController.m b/Controller/PBGitResetController.m index f0d199a..773a74d 100644 --- a/Controller/PBGitResetController.m +++ b/Controller/PBGitResetController.m @@ -10,6 +10,8 @@ #import "PBGitRepository.h" #import "PBCommand.h" +static NSString * const kCommandKey = @"command"; + @implementation PBGitResetController - (id) initWithRepository:(PBGitRepository *) repo { @@ -20,11 +22,23 @@ } - (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"; - [cmd invoke]; + + NSMutableDictionary *info = [NSMutableDictionary dictionaryWithObject:cmd forKey:kCommandKey]; + + [alert beginSheetModalForWindow:[repository.windowController window] + modalDelegate:self + didEndSelector:@selector(confirmResetSheetDidEnd:returnCode:contextInfo:) + contextInfo:info]; } - (void) reset { @@ -56,5 +70,18 @@ [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 From cb59e86a813a203a5a79257cbc0ad4daf56e3c05 Mon Sep 17 00:00:00 2001 From: Tomasz Krasnyk Date: Sun, 28 Nov 2010 23:38:10 +0100 Subject: [PATCH 21/23] Deleted stash commands from ref menu --- PBRefMenuItem.m | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/PBRefMenuItem.m b/PBRefMenuItem.m index a42b5be..aaaee1f 100644 --- a/PBRefMenuItem.m +++ b/PBRefMenuItem.m @@ -141,16 +141,6 @@ [item setTarget:target]; [item setRefish:ref]; } - - NSArray *cmds = [PBStashCommandFactory commandsForObject:ref repository:repo]; - if ([cmds count] > 0) { - for (PBCommand *cmd in cmds) { - PBCommandMenuItem *item = [[PBCommandMenuItem alloc] initWithCommand:cmd]; - [item setEnabled:YES]; - [items addObject:item]; - [item release]; - } - } return items; } From 33e21e2604b586a677bc39c361bb83b3f4342e25 Mon Sep 17 00:00:00 2001 From: Tomasz Krasnyk Date: Mon, 29 Nov 2010 00:10:17 +0100 Subject: [PATCH 22/23] Added new icons for file status. When untracked file is added to index than it has added file icon. --- File Markers/added_file.png | Bin 0 -> 397 bytes File Markers/conflicted_file.png | Bin 0 -> 387 bytes File Markers/deleted_file.png | Bin 0 -> 397 bytes File Markers/ignored_file.png | Bin 0 -> 286 bytes File Markers/modified_file.png | Bin 0 -> 425 bytes File Markers/renamed_file.png | Bin 0 -> 419 bytes File Markers/unversioned_file.png | Bin 0 -> 392 bytes GitX.xcodeproj/project.pbxproj | 40 +++++++++++++++++++++++++++--- PBChangedFile.h | 4 ++- PBChangedFile.m | 17 +++++++++---- PBGitIndexController.m | 8 +++++- 11 files changed, 58 insertions(+), 11 deletions(-) create mode 100644 File Markers/added_file.png create mode 100644 File Markers/conflicted_file.png create mode 100644 File Markers/deleted_file.png create mode 100644 File Markers/ignored_file.png create mode 100644 File Markers/modified_file.png create mode 100644 File Markers/renamed_file.png create mode 100644 File Markers/unversioned_file.png diff --git a/File Markers/added_file.png b/File Markers/added_file.png new file mode 100644 index 0000000000000000000000000000000000000000..ad08fae2d588c89b504b272a82ec70f1c3090f6c GIT binary patch literal 397 zcmV;80doF{P)TgOz+DSRow${)4UoWa=LVd45x{gtCYw12Y2$!*3)_ za1CIq|Na5fib7@#XCJL&`1t(=P?H5%Aw<((ga(*mZWdt%89_aU8_y0i+<1PNK~>BO ztl=+`4J-&7{xT>@n1cnAY-Yj3k(XVR;q9lV41fRqMb_{KtU*WGjbY>YHim0Y4uAt7 z$h3w*L(-1n;QPhEp#2Bd0FH;g-F}j=p!^4>|A9^X2cv<3^8ep|hK`sMka*CNa7GHk rzfgC>4EP7e#!5bL8%RnT009O7Kf3u@m|5z_00000NkvXXu0mjfUt+71 literal 0 HcmV?d00001 diff --git a/File Markers/conflicted_file.png b/File Markers/conflicted_file.png new file mode 100644 index 0000000000000000000000000000000000000000..a633ecf4eb3bab52ca7a866e72d1cb2a2b2ede77 GIT binary patch literal 387 zcmV-}0et?6P))Um&954Jmj|X44lep?Y(G8}4Q*tA&&;P}rjN zHEh*t_#BUQEy_zkYP3+I)Z9mDuc`B7I>qzNmD>FU2$B!&lfp_dTA6dpon0P!d$*y! r!{I{j^Je7W%E6%mqW@lvF98MsCKm!pAR2cE00000NkvXXu0mjf>=&tq literal 0 HcmV?d00001 diff --git a/File Markers/ignored_file.png b/File Markers/ignored_file.png new file mode 100644 index 0000000000000000000000000000000000000000..c4813fb57ab11aabe39d8a9a714cdc918eb7e09e GIT binary patch literal 286 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&k$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1G2RvOILn>}fnPkX!Sb@jYcdB=YQ_{H^)&`r5(qCIv@mi&K z&nTY86M0&dBQxhDM@E|%XHSlOy|QxO;|it&%yrTFg-q{DW8W*XSiGMQbgJxr`KBF9 zrx@@!?@(+zDf8fngmUD*{M&9qvT`qutcrSl+U{B9vN=2jPg5f`5_%Rc_-?m4VNZ}o z^|R1zUsEK(nypupj~A-Ep0hhIbJns|NtWzv8GK%vK@abqW1ReZ ipSr`J-==mDhPfQk%Vg$ z1qD%wt(~L@)?(o=u(PqWvJ*kD*2>l+bQyD8I5fzk}B5*r<>&)!k*1C6d zv+T^9dGq!n=iDxUP5f;gM+|7cpWMVh^=CMjB2C$B3aj425*zzMWe(F@)we!@b?Qw{ z^Z`jAB3MHpV|Z`Ww=V9qMZbKcq5#Ct9&TW;II6+U{Ry!h zJnf%htUQ6C$pQ>_5DOiMtmn%H$1n3A7$4Du?&~KgF+P?9EcpWgI(|y4WeqluuF(7H z>Uj=ON`?nC*^tZ#t@B&-+TR$SiIs{BE=2=C)krd)jF90U_G*YL3n;D3bDXqGpd^W2 zZ^HHZL6En$w5|IzyOYqNSY7l=Boq`8#VAuxRGeB{RzURMU*lJR0RSPF0GM|8Dq{cu N002ovPDHLkV1nEGum%7C literal 0 HcmV?d00001 diff --git a/File Markers/unversioned_file.png b/File Markers/unversioned_file.png new file mode 100644 index 0000000000000000000000000000000000000000..62a936101d6d0851c965210a6093a08f2c532ebc GIT binary patch literal 392 zcmV;30eAk1P)+cwuLDvpcu9YNrR^4b1KL zGqV>NV@?1Z;BU`)WC=-@oYmF)EsQo68rniC7hudR?_zQNs2@9;8s5P84|0GQ?4TS- zYTCOJi;{bZA{(i5jZ;j|Z(34{;d2{bgGVpKLJ$W{8f+WUR25pKc)QzyvDFco$h*)F z2OovTJ!G9@R92d>)8MmvDF literal 0 HcmV?d00001 diff --git a/GitX.xcodeproj/project.pbxproj b/GitX.xcodeproj/project.pbxproj index 5dfb9ea..dae5822 100644 --- a/GitX.xcodeproj/project.pbxproj +++ b/GitX.xcodeproj/project.pbxproj @@ -42,6 +42,13 @@ 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 */; }; @@ -160,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 */; }; @@ -276,7 +282,6 @@ 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 = ""; }; - 21025CA6129487C200D87200 /* defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = defs.h; 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 = ""; }; @@ -306,6 +311,13 @@ 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 = ""; }; @@ -689,7 +701,6 @@ 21230ED41285ED760046E5A1 /* View */ = { isa = PBXGroup; children = ( - 21025CA6129487C200D87200 /* defs.h */, 21230ED71285EDAF0046E5A1 /* PBArgumentPicker.h */, 21230ED81285EDAF0046E5A1 /* PBArgumentPicker.m */, 21CF0B22129C7ED90065B37C /* TrackableOutlineView.h */, @@ -714,6 +725,20 @@ 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 = ( @@ -741,6 +766,7 @@ 29B97315FDCFA39411CA2CEA /* Other Sources */ = { isa = PBXGroup; children = ( + 212A499412A3121D009DAFAD /* File Markers */, 2123121B128735E90046E5A1 /* submodule-notmatching-index.png */, 2123121C128735E90046E5A1 /* submodule-matching-index.png */, 2123121D128735E90046E5A1 /* submodule-empty.png */, @@ -1337,7 +1363,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 */, @@ -1383,6 +1408,13 @@ 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; }; 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/PBGitIndexController.m b/PBGitIndexController.m index 48d727c..02a5fce 100644 --- a/PBGitIndexController.m +++ b/PBGitIndexController.m @@ -251,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 From 51d56b983e2209ca747f7ad6f1776a335eca0859 Mon Sep 17 00:00:00 2001 From: German Laullom Date: Tue, 7 Dec 2010 12:47:28 -0800 Subject: [PATCH 23/23] correct libgit2 submodule. ?? --- PBGitSHA.m | 2 +- libgit2 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PBGitSHA.m b/PBGitSHA.m index 6aff86f..1745133 100644 --- a/PBGitSHA.m +++ b/PBGitSHA.m @@ -82,7 +82,7 @@ - (NSString *)string { if (!string) { - char *hex = git_oid_mkhex(&oid); + char *hex = git_oid_allocfmt(&oid); if (hex == NULL) return nil; string = [NSString stringWithUTF8String:hex]; diff --git a/libgit2 b/libgit2 index bda29d0..998a7bf 160000 --- a/libgit2 +++ b/libgit2 @@ -1 +1 @@ -Subproject commit bda29d0f7bc59a821b03c716562aef6ea3b5903a +Subproject commit 998a7bf824c5faca0f9766c9b89bb73ec1315272