First take on graphing

This implements some sort of graph shower like Gitk has. However, it still
has bugs and can't do color very well.
This commit is contained in:
Pieter de Bie
2008-06-18 01:02:29 +02:00
parent ede8892dc9
commit 52d9402513
9 changed files with 247 additions and 48 deletions
+4 -3
View File
@@ -225,8 +225,9 @@
if (![[aTableColumn identifier] isEqualToString:@"subject"])
return;
NSNumber* n = [NSNumber numberWithInt:(rowIndex % 2)];
[aCell setCommit:n];
if (self.repository.revisionList.grapher) {
PBGitGrapher* g = self.repository.revisionList.grapher;
[aCell setCellInfo: [g cellInfoForRow:rowIndex]];
}
}
@end
+8 -2
View File
@@ -32,6 +32,7 @@
F5B721C40E05CF7E00AF29DC /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = F5B721C20E05CF7E00AF29DC /* MainMenu.xib */; };
F5DFFA6C0E075D8800617813 /* PBEasyFS.m in Sources */ = {isa = PBXBuildFile; fileRef = F5DFFA6B0E075D8800617813 /* PBEasyFS.m */; };
F5FF4E180E0829C20006317A /* PBGitRevList.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FF4E170E0829C20006317A /* PBGitRevList.m */; };
F5FF4E7A0E082E440006317A /* PBGitGrapher.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FF4E790E082E440006317A /* PBGitGrapher.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -79,6 +80,8 @@
F5DFFA6B0E075D8800617813 /* PBEasyFS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBEasyFS.m; sourceTree = "<group>"; };
F5FF4E160E0829C20006317A /* PBGitRevList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitRevList.h; sourceTree = "<group>"; };
F5FF4E170E0829C20006317A /* PBGitRevList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitRevList.m; sourceTree = "<group>"; };
F5FF4E780E082E440006317A /* PBGitGrapher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitGrapher.h; sourceTree = "<group>"; };
F5FF4E790E082E440006317A /* PBGitGrapher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitGrapher.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -185,6 +188,8 @@
F56174540E05887E001DCD79 /* Git */ = {
isa = PBXGroup;
children = (
F5FF4E780E082E440006317A /* PBGitGrapher.h */,
F5FF4E790E082E440006317A /* PBGitGrapher.m */,
F5945E150E02B0C200706420 /* PBGitRepository.h */,
F5945E160E02B0C200706420 /* PBGitRepository.m */,
F56524EE0E02D45200F03B52 /* PBGitCommit.h */,
@@ -317,6 +322,7 @@
F5DFFA6C0E075D8800617813 /* PBEasyFS.m in Sources */,
F50FE0E30E07BE9600854FCD /* PBGitRevisionCell.m in Sources */,
F5FF4E180E0829C20006317A /* PBGitRevList.m in Sources */,
F5FF4E7A0E082E440006317A /* PBGitGrapher.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -352,10 +358,10 @@
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = GitTest_Prefix.pch;
GCC_PREFIX_HEADER = GitX_Prefix.pch;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Applications";
PRODUCT_NAME = GitTest;
PRODUCT_NAME = GitX;
WRAPPER_EXTENSION = app;
ZERO_LINK = YES;
};
+42
View File
@@ -0,0 +1,42 @@
//
// PBGitGrapher.h
// GitX
//
// Created by Pieter de Bie on 17-06-08.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "PBGitCommit.h"
struct PBGitGraphColumn {
NSString* commit; // Commit that we're looking for
int color;
};
#define PBGitMaxColumns 10
struct PBGitGraphCellInfo {
struct PBGitGraphColumn columns[PBGitMaxColumns];
int upperMapping[PBGitMaxColumns]; //How are the offsets compared to previous cell?
int lowerMapping[PBGitMaxColumns]; //How are the offsets compared to this cell?
int position;
NSString* commit; // Commit in cell
int numColumns;
int numNewColumns;
};
void add_commit_to_graph(struct PBGitGraphCellInfo* info, NSString* parent, int* mapping_index);
typedef struct PBGitGraphCellInfo PBGitCellInfo;
@interface PBGitGrapher : NSObject {
PBGitCellInfo* cellsInfo;
}
- (void) parseCommits: (NSArray *) array;
- (struct PBGitGraphCellInfo) cellInfoForRow: (int) row;
@end
+87
View File
@@ -0,0 +1,87 @@
//
// PBGitGrapher.m
// GitX
//
// Created by Pieter de Bie on 17-06-08.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import "PBGitGrapher.h"
#import "PBGitCommit.h"
@implementation PBGitGrapher
static NSColor** PBGitGraphColors;
- (void) parseCommits: (NSArray *) commits
{
cellsInfo = malloc(sizeof(struct PBGitGraphCellInfo) * [commits count]);
memset(cellsInfo, 0, sizeof(struct PBGitGraphCellInfo) * [commits count]);
int row = 0;
struct PBGitGraphCellInfo *previous = nil;
for (PBGitCommit* commit in commits) {
struct PBGitGraphCellInfo *info = &(cellsInfo[row]);
info->commit = commit.sha;
info->numColumns = 0;
int i = 0, newPos = -1;
BOOL didFirst = NO;
// First, iterate over earlier columns and pass through any that don't want this commit
if (previous != nil) {
for (i = 0; i < 10; i++) {
if ((previous->columns[i].commit) == nil)
continue;
if ([previous->columns[i].commit isEqualToString:info->commit]) {
if (!didFirst) {
didFirst = YES;
info->position = info->numColumns++;
info->columns[info->position].commit = [commit.parents objectAtIndex:0];
info->columns[info->position].color = previous->columns[i].color;
}
newPos = info->position;
}
else {
newPos = info->numColumns++;
info->columns[newPos] = previous->columns[i];
if (newPos > 1)
info->columns[newPos].color = (info->columns[newPos - 1].color + 1) % 4;
}
info->upperMapping[newPos] = i;
if (previous)
previous->lowerMapping[i] = newPos;
}
}
//Add your own parents!
BOOL doFirst = YES;
for (NSString* parent in commit.parents) {
if (doFirst) {
doFirst = NO;
if (didFirst)
continue;
info->position = info->numColumns++;
info->columns[info->position].commit = parent;
continue;
}
info->columns[info->numColumns++].commit = parent;
}
previous = info;
++row;
}
}
- (struct PBGitGraphCellInfo) cellInfoForRow: (int) row
{
return cellsInfo[row];
}
- (void) finalize
{
free(cellsInfo);
[super finalize];
}
@end
+1 -1
View File
@@ -14,7 +14,7 @@
@implementation PBGitRepository
@synthesize path;
@synthesize path, revisionList;
static NSString* gitPath;
+ (void) initialize
+3
View File
@@ -12,10 +12,13 @@
@interface PBGitRevList : NSObject {
NSArray* commits;
NSArray* parameters;
id grapher;
id repository;
}
- initWithRepository:(id)repo andRevListParameters:(NSArray*) params;
@property(retain) NSArray* commits;
@property(retain) id grapher;
@end
+9 -2
View File
@@ -9,10 +9,11 @@
#import "PBGitRevList.h"
#import "PBGitRepository.h"
#import "PBGitCommit.h"
#import "PBGitGrapher.h"
@implementation PBGitRevList
@synthesize commits;
@synthesize commits, grapher;
- initWithRepository: (id) repo andRevListParameters: (NSArray*) params
{
parameters = params;
@@ -72,10 +73,16 @@
}
[self performSelectorOnMainThread:@selector(setCommits:) withObject:newArray waitUntilDone:YES];
PBGitGrapher* g = [[PBGitGrapher alloc] init];
[g parseCommits: self.commits];
[self performSelectorOnMainThread:@selector(setGrapher:) withObject:g waitUntilDone:YES];
[self performSelectorOnMainThread:@selector(setCommits:) withObject:newArray waitUntilDone:YES];
NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:start];
NSLog(@"Loaded %i commits in %f seconds", num, duration);
[NSThread exit];
}
@end
+4 -2
View File
@@ -7,10 +7,12 @@
//
#import <Cocoa/Cocoa.h>
#import "PBGitGrapher.h"
@interface PBGitRevisionCell : NSTextFieldCell {
NSNumber* commit;
PBGitCellInfo cellInfo;
BOOL isReady;
}
@property(retain) NSNumber* commit;
@property(assign) PBGitCellInfo cellInfo;
@end
+89 -38
View File
@@ -10,15 +10,90 @@
@implementation PBGitRevisionCell
@synthesize commit;
@synthesize cellInfo;
-(void) setCellInfo: (PBGitCellInfo) info
{
isReady = YES;
cellInfo = info;
}
- (id) initWithCoder: (id) coder
{
self = [super initWithCoder:coder];
if (self != nil) {
isReady = NO;
}
return self;
}
- (void) drawLineForColumn: (int)c inRect: (NSRect) r
{
NSArray* col = [NSArray arrayWithObjects:[NSColor redColor], [NSColor blueColor],
[NSColor orangeColor], [NSColor blackColor], [NSColor greenColor], nil];
int columnWidth = 10;
NSPoint origin = r.origin;
NSPoint source;
NSPoint center;
NSPoint destination;
center = NSMakePoint( origin.x + columnWidth * c, origin.y + r.size.height * 0.5);
if (cellInfo.upperMapping[c] == cellInfo.position && c != cellInfo.upperMapping[c]) {
source = NSMakePoint(origin.x + columnWidth * cellInfo.upperMapping[c], origin.y + r.size.height * 0.5);
destination = NSMakePoint( origin.x + columnWidth * cellInfo.lowerMapping[c], origin.y + r.size.height);
} else if (cellInfo.lowerMapping[c] == cellInfo.position && c != cellInfo.lowerMapping[c]) {
source = NSMakePoint( origin.x + columnWidth * cellInfo.upperMapping[c], origin.y);
destination = NSMakePoint( origin.x + columnWidth * c, origin.y + r.size.height);
} else {
source = NSMakePoint( origin.x + columnWidth * cellInfo.upperMapping[c], origin.y);
destination = NSMakePoint( origin.x + columnWidth * cellInfo.lowerMapping[c], origin.y + r.size.height);
}
[[col objectAtIndex:cellInfo.columns[c].color] set];
NSBezierPath * path = [NSBezierPath bezierPath];
[path setLineWidth:2];
[path moveToPoint:source];
[path lineToPoint: center];
[path lineToPoint: destination];
[path stroke];
}
- (void) drawCircleForColumn: (int) c inRect: (NSRect) r
{
NSArray* col = [NSArray arrayWithObjects:[NSColor redColor], [NSColor blueColor],
[NSColor orangeColor], [NSColor blackColor], [NSColor greenColor], nil];
int columnWidth = 10;
NSPoint origin = r.origin;
NSPoint columnOrigin = { origin.x + columnWidth * c, origin.y};
NSRect oval = { columnOrigin.x - 5, columnOrigin.y + r.size.height * 0.5 - 5, 10, 10};
NSBezierPath * path = [NSBezierPath bezierPath];
path = [NSBezierPath bezierPathWithOvalInRect:oval];
[[col objectAtIndex:cellInfo.columns[c].color] set];
[path fill];
NSRect smallOval = { columnOrigin.x - 3, columnOrigin.y + r.size.height * 0.5 - 3, 6, 6};
[[NSColor whiteColor] set];
path = [NSBezierPath bezierPathWithOvalInRect:smallOval];
[path fill];
}
- (void) drawWithFrame: (NSRect) rect inView:(NSView *)view
{
// Don't do all this drawing for now.
[super drawWithFrame:rect inView:view];
return;
float pathWidth = 20;
if (!isReady)
return [super drawWithFrame:rect inView:view];
float pathWidth = 10 + 10 * cellInfo.numColumns;
NSRect ownRect;
NSDivideRect(rect, &ownRect, &rect, pathWidth, NSMinXEdge);
@@ -26,42 +101,18 @@
// Adjust by removing the border
ownRect.size.height += 2;
ownRect.origin.y -= 1;
ownRect.origin.x += 10;
NSPoint origin = ownRect.origin;
NSPoint middle = { origin.x + pathWidth / 2, origin.y + ownRect.size.height * 0.5 };
[[NSColor redColor] set];
NSBezierPath * path = [NSBezierPath bezierPath];
[path moveToPoint:NSMakePoint(middle.x, origin.y)];
[path setLineWidth:2];
[path lineToPoint: NSMakePoint(middle.x, origin.y + ownRect.size.height)];
[path stroke];
[path setLineWidth:1];
NSRect oval = { middle.x - 5, middle.y -5, 10, 10};
[[NSColor orangeColor] set];
path = [NSBezierPath bezierPathWithOvalInRect:oval];
[path fill];
if ([self.commit intValue] == 0)
[[NSColor redColor] set];
else
[[NSColor blueColor] set];
[path stroke];
NSRect smallOval = { middle.x - 3, middle.y - 3, 6, 6};
[[NSColor whiteColor] set];
path = [NSBezierPath bezierPathWithOvalInRect:smallOval];
[path fill];
[[NSColor blackColor] set];
[path stroke];
int column = 0;
for (column = 0; column < cellInfo.numColumns; column++) {
if (cellInfo.columns[column].color >= 0)
[self drawLineForColumn: column inRect: ownRect];
}
[self drawCircleForColumn: cellInfo.position inRect: ownRect];
[super drawWithFrame:rect inView:view];
[[NSColor blueColor] set];
//[path stroke];
isReady = NO;
}
@end