Merge branch 'display_tags'

* display_tags:
  Grapher: add coloring to ref labels
  Fix a crashing bug in PBGitRepository
  Add a PBGitRef, a class to represent refs
  Some minor cleanup of the commit-ref drawing.
  Grapher: draw ref names
  Grapher: dereference annotated tags
  Grapher: add first part of displaying refs
This commit is contained in:
Pieter de Bie
2008-09-06 22:31:29 +02:00
12 changed files with 242 additions and 17 deletions
+6
View File
@@ -38,6 +38,7 @@
F58A8F280E043698007E3FC0 /* commits.css in Resources */ = {isa = PBXBuildFile; fileRef = F58A8F270E043698007E3FC0 /* commits.css */; };
F5945E170E02B0C200706420 /* PBGitRepository.m in Sources */ = {isa = PBXBuildFile; fileRef = F5945E160E02B0C200706420 /* PBGitRepository.m */; };
F5B721C40E05CF7E00AF29DC /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = F5B721C20E05CF7E00AF29DC /* MainMenu.xib */; };
F5C007750E731B48007B84B2 /* PBGitRef.m in Sources */ = {isa = PBXBuildFile; fileRef = F5C007740E731B48007B84B2 /* PBGitRef.m */; };
F5C6F68D0E65FF9300478D97 /* PBGitLane.m in Sources */ = {isa = PBXBuildFile; fileRef = F5C6F68C0E65FF9300478D97 /* PBGitLane.m */; };
F5DFFA6C0E075D8800617813 /* PBEasyFS.m in Sources */ = {isa = PBXBuildFile; fileRef = F5DFFA6B0E075D8800617813 /* PBEasyFS.m */; };
F5FF4E180E0829C20006317A /* PBGitRevList.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FF4E170E0829C20006317A /* PBGitRevList.m */; };
@@ -107,6 +108,8 @@
F5945E150E02B0C200706420 /* PBGitRepository.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitRepository.h; sourceTree = "<group>"; };
F5945E160E02B0C200706420 /* PBGitRepository.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitRepository.m; sourceTree = "<group>"; };
F5B721C30E05CF7E00AF29DC /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = "<group>"; };
F5C007730E731B48007B84B2 /* PBGitRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitRef.h; sourceTree = "<group>"; };
F5C007740E731B48007B84B2 /* PBGitRef.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitRef.m; sourceTree = "<group>"; };
F5C6F68B0E65FF9300478D97 /* PBGitLane.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitLane.h; sourceTree = "<group>"; };
F5C6F68C0E65FF9300478D97 /* PBGitLane.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitLane.m; sourceTree = "<group>"; };
F5DFFA6A0E075D8800617813 /* PBEasyFS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBEasyFS.h; sourceTree = "<group>"; };
@@ -305,6 +308,8 @@
F5C6F6750E65FE2B00478D97 /* Graphing */ = {
isa = PBXGroup;
children = (
F5C007730E731B48007B84B2 /* PBGitRef.h */,
F5C007740E731B48007B84B2 /* PBGitRef.m */,
F50FE0E10E07BE9600854FCD /* PBGitRevisionCell.h */,
F50FE0E20E07BE9600854FCD /* PBGitRevisionCell.m */,
F56CC7270E65E0AD004307B4 /* PBGitGraphLine.h */,
@@ -419,6 +424,7 @@
F56CC7290E65E0AD004307B4 /* PBGitGraphLine.m in Sources */,
F56CC7320E65E0E5004307B4 /* PBGraphCellInfo.m in Sources */,
F5C6F68D0E65FF9300478D97 /* PBGitLane.m in Sources */,
F5C007750E731B48007B84B2 /* PBGitRef.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+2
View File
@@ -21,8 +21,10 @@ struct PBGitGraphColumn {
@interface PBGitGrapher : NSObject {
NSMutableArray* cellsInfo;
PBGitRepository* repository;
}
- (id) initWithRepository: (PBGitRepository*) repo;
- (void) parseCommits: (NSArray *) array;
- (PBGraphCellInfo*) cellInfoForRow: (int) row;
@end
+13 -1
View File
@@ -12,12 +12,21 @@
@implementation PBGitGrapher
- (id) initWithRepository: (PBGitRepository*) repo
{
repository = repo;
return self;
}
- (void) parseCommits: (NSArray *) commits
{
cellsInfo = [NSMutableArray arrayWithCapacity: [commits count]];
int row = 0;
NSDictionary* refs = nil;
if (repository)
refs = repository.refs;
PBGraphCellInfo* previous;
NSMutableArray* previousLanes = [NSMutableArray array];
@@ -120,7 +129,10 @@
++row;
previous = [[PBGraphCellInfo alloc] initWithPosition:newPos andLines:lines];
if (refs && [refs objectForKey:commit.sha])
previous.refs = [refs objectForKey:commit.sha];
// If a parent was added, we have room to not indent.
if (addedParent)
previous.numColumns = [currentLanes count] - 1;
+22
View File
@@ -0,0 +1,22 @@
//
// PBGitRef.h
// GitX
//
// Created by Pieter de Bie on 06-09-08.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface PBGitRef : NSObject {
NSString* ref;
}
- (NSString*) shortName;
- (NSString*) type;
+ (PBGitRef*) refFromString: (NSString*) s;
- (PBGitRef*) initWithString: (NSString*) s;
@property(readonly) NSString* ref;
@end
+44
View File
@@ -0,0 +1,44 @@
//
// PBGitRef.m
// GitX
//
// Created by Pieter de Bie on 06-09-08.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import "PBGitRef.h"
@implementation PBGitRef
@synthesize ref;
- (NSString*) shortName
{
if ([self type])
return [ref substringFromIndex:[[self type] length] + 7];
return ref;
}
- (NSString*) type
{
if ([ref hasPrefix:@"refs/heads"])
return @"head";
if ([ref hasPrefix:@"refs/tags"])
return @"tag";
if ([ref hasPrefix:@"refs/remotes"])
return @"remote";
return nil;
}
+ (PBGitRef*) refFromString: (NSString*) s
{
return [[PBGitRef alloc] initWithString:s];
}
- (PBGitRef*) initWithString: (NSString*) s
{
ref = s;
return self;
}
@end
+3 -2
View File
@@ -15,6 +15,7 @@ extern NSString* PBGitRepositoryErrorDomain;
PBGitRevList* revisionList;
NSArray* branches;
NSString* currentBranch;
NSDictionary* refs;
}
- (NSFileHandle*) handleForCommand:(NSString*) cmd;
@@ -22,7 +23,7 @@ extern NSString* PBGitRepositoryErrorDomain;
- (NSString*) outputForCommand:(NSString*) cmd;
- (NSString*) outputForArguments:(NSArray*) args;
- (void) readBranches;
- (void) readRefs;
- (void) readCurrentBranch;
- (NSString*) parseSymbolicReference:(NSString*) ref;
@@ -34,5 +35,5 @@ extern NSString* PBGitRepositoryErrorDomain;
@property (readonly) PBGitRevList* revisionList;
@property (assign) NSArray* branches;
@property (assign) NSString* currentBranch;
@property (assign) NSDictionary* refs;
@end
+24 -10
View File
@@ -17,7 +17,7 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain";
@implementation PBGitRepository
@synthesize revisionList, branches, currentBranch;
@synthesize revisionList, branches, currentBranch, refs;
static NSString* gitPath;
+ (void) initialize
@@ -112,7 +112,7 @@ static NSString* gitPath;
}
if (success) {
[self readBranches];
[self readRefs];
[self readCurrentBranch];
revisionList = [[PBGitRevList alloc] initWithRepository:self andRevListParameters:[NSArray array]];
}
@@ -139,21 +139,35 @@ static NSString* gitPath;
[controller release];
}
- (void) readBranches
- (void) readRefs
{
NSString* output = [PBEasyPipe outputForCommand:gitPath withArgs:[NSArray arrayWithObjects:@"for-each-ref", @"refs/heads", nil] inDir: self.fileURL.path];
NSString* output = [PBEasyPipe outputForCommand:gitPath withArgs:[NSArray arrayWithObjects:@"for-each-ref", @"--format=%(refname) %(objecttype) %(objectname) %(*objectname)", @"refs", nil] inDir: self.fileURL.path];
NSArray* lines = [output componentsSeparatedByString:@"\n"];
NSMutableDictionary* newRefs = [NSMutableDictionary dictionary];
NSMutableArray* newBranches = [NSMutableArray array];
for (NSString* line in lines) {
NSString* substr = [line substringWithRange: NSMakeRange(40,19)];
if (![substr isEqualToString:@" commit\trefs/heads/"]) {
NSLog(@"Cannot parse branch %@. (%@)", line, substr);
continue;
NSArray* components = [line componentsSeparatedByString:@" "];
NSString* ref = [components objectAtIndex:0];
NSString* type = [components objectAtIndex:1];
NSString* sha;
if ([type isEqualToString:@"tag"] && [components count] == 4)
sha = [components objectAtIndex:3];
else
sha = [components objectAtIndex:2];
if ([ref length] > 11 && [[ref substringToIndex:11] isEqualToString:@"refs/heads/"]) {
NSString* branch = [ref substringFromIndex:11];
[newBranches addObject: branch];
}
NSString* branch = [line substringFromIndex:59];
[newBranches addObject: branch];
NSMutableArray* curRefs;
if (curRefs = [newRefs objectForKey:sha])
[curRefs addObject:ref];
else
[newRefs setObject:[NSMutableArray arrayWithObject:ref] forKey:sha];
}
self.branches = newBranches;
self.refs = newRefs;
}
- (void) readCurrentBranch
+1 -1
View File
@@ -18,7 +18,7 @@
}
- initWithRepository:(id)repo andRevListParameters:(NSArray*) params;
- readCommits;
- (void) readCommits;
@property(retain) NSArray* commits;
@property(retain) id grapher;
+1 -1
View File
@@ -103,7 +103,7 @@
[self performSelectorOnMainThread:@selector(setCommits:) withObject:newArray waitUntilDone:YES];
PBGitGrapher* g = [[PBGitGrapher alloc] init];
PBGitGrapher* g = [[PBGitGrapher alloc] initWithRepository: repository];
[g parseCommits: self.commits];
[self performSelectorOnMainThread:@selector(setGrapher:) withObject:g waitUntilDone:YES];
[self performSelectorOnMainThread:@selector(setCommits:) withObject:newArray waitUntilDone:YES];
+123 -1
View File
@@ -7,7 +7,54 @@
//
#import "PBGitRevisionCell.h"
#import "PBGitRef.h"
@implementation NSBezierPath (RoundedRectangle)
+ (NSBezierPath *)bezierPathWithRoundedRect: (NSRect) aRect cornerRadius: (double) cRadius
{
double left = aRect.origin.x, bottom = aRect.origin.y, width = aRect.size.width, height = aRect.size.height;
//now, crop the radius so we don't get weird effects
double lesserDim = width < height ? width : height;
if ( cRadius > lesserDim / 2 )
{
cRadius = lesserDim / 2;
}
//these points describe the rectangle as start and stop points of the
//arcs making up its corners --points c, e, & g are implicit endpoints of arcs
//and are unnecessary
NSPoint a = NSMakePoint( 0, cRadius ), b = NSMakePoint( 0, height - cRadius ),
d = NSMakePoint( width - cRadius, height ), f = NSMakePoint( width, cRadius ),
h = NSMakePoint( cRadius, 0 );
//these points describe the center points of the corner arcs
NSPoint cA = NSMakePoint( cRadius, height - cRadius ),
cB = NSMakePoint( width - cRadius, height - cRadius ),
cC = NSMakePoint( width - cRadius, cRadius ),
cD = NSMakePoint( cRadius, cRadius );
//start
NSBezierPath *bp = [NSBezierPath bezierPath];
[bp moveToPoint: a ];
[bp lineToPoint: b ];
[bp appendBezierPathWithArcWithCenter: cA radius: cRadius startAngle:180 endAngle:90 clockwise: YES];
[bp lineToPoint: d ];
[bp appendBezierPathWithArcWithCenter: cB radius: cRadius startAngle:90 endAngle:0 clockwise: YES];
[bp lineToPoint: f ];
[bp appendBezierPathWithArcWithCenter: cC radius: cRadius startAngle:0 endAngle:270 clockwise: YES];
[bp lineToPoint: h ];
[bp appendBezierPathWithArcWithCenter: cD radius: cRadius startAngle:270 endAngle:180 clockwise: YES];
[bp closePath];
//Transform path to rectangle's origin
NSAffineTransform *transform = [NSAffineTransform transform];
[transform translateXBy: left yBy: bottom];
[bp transformUsingAffineTransform: transform];
return bp; //it's already been autoreleased
}
@end
@implementation PBGitRevisionCell
@@ -63,7 +110,11 @@
- (void) drawCircleForColumn: (int) c inRect: (NSRect) r
{
[[NSColor blackColor] set];
if (!cellInfo.refs)
[[NSColor blackColor] set];
else
[[NSColor redColor] set];
int columnWidth = 10;
NSPoint origin = r.origin;
NSPoint columnOrigin = { origin.x + columnWidth * c, origin.y};
@@ -82,6 +133,75 @@
[path fill];
}
- (NSMutableDictionary*) attributesForRefLabelSelected: (BOOL) selected
{
NSMutableDictionary *attributes = [[[NSMutableDictionary alloc] initWithCapacity:2] autorelease];
NSMutableParagraphStyle* style = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
[style setAlignment:NSCenterTextAlignment];
[attributes setObject:style forKey:NSParagraphStyleAttributeName];
[attributes setObject:[NSFont fontWithName:@"Helvetica" size:9] forKey:NSFontAttributeName];
//if (selected)
// [attributes setObject:[NSColor alternateSelectedControlTextColor] forKey:NSForegroundColorAttributeName];
return attributes;
}
- (NSColor*) colorForRef: (PBGitRef*) ref
{
NSString* type = [ref type];
if ([type isEqualToString:@"head"])
return [NSColor yellowColor];
else if ([type isEqualToString:@"remote"])
return [NSColor greenColor];
else if ([type isEqualToString:@"tag"])
return [NSColor cyanColor];
return [NSColor yellowColor];
}
- (void) drawRefsInRect: (NSRect*) rect
{
static const float ref_padding = 10.0f;
static const float ref_spacing = 2.0f;
NSRect refRect = (NSRect){rect->origin, rect->size};
if([self isHighlighted])
[[NSColor whiteColor] setStroke];
else
[[NSColor blackColor] setStroke];
int index;
for (index = 0; index < [cellInfo.refs count]; ++index) {
PBGitRef* ref = [PBGitRef refFromString:[cellInfo.refs objectAtIndex:index]];
NSMutableDictionary* attributes = [self attributesForRefLabelSelected:[self isHighlighted]];
NSSize refSize = [[ref shortName] sizeWithAttributes:attributes];
refRect.size.width = refSize.width + ref_padding;
refRect.size.height = refSize.height;
refRect.origin.y += (rect->size.height - refRect.size.height) / 2;
// Round rects to 0.5 pixels in order to draw only a single pixel
refRect.origin.x = round(refRect.origin.x) - 0.5;
refRect.origin.y = round(refRect.origin.y) - 0.5;
NSBezierPath *border = [NSBezierPath bezierPathWithRoundedRect:refRect cornerRadius: 2.0];
[[self colorForRef: ref] set];
[border fill];
[[ref shortName] drawInRect:refRect withAttributes:attributes];
[border stroke];
refRect.origin.x += (int)refRect.size.width + ref_spacing;
}
rect->size.width -= refRect.origin.x - rect->origin.x;
rect->origin.x = refRect.origin.x;
}
- (void) drawWithFrame: (NSRect) rect inView:(NSView *)view
{
if (!isReady)
@@ -101,6 +221,8 @@
[self drawCircleForColumn: cellInfo.position inRect: ownRect];
if (cellInfo.refs)
[self drawRefsInRect:&rect];
[super drawWithFrame:rect inView:view];
isReady = NO;
+2
View File
@@ -14,8 +14,10 @@
int position;
NSArray* lines;
int numColumns;
NSArray* refs;
}
@property(readonly) NSArray* lines;
@property(retain) NSArray* refs;
@property(assign) int position, numColumns;
- (id)initWithPosition: (int) p andLines: (NSArray*) l;
+1 -1
View File
@@ -10,7 +10,7 @@
@implementation PBGraphCellInfo
@synthesize lines, position, numColumns;
@synthesize lines, position, numColumns, refs;
- (id)initWithPosition: (int) p andLines: (NSArray*) l
{
position = p;