mirror of
https://github.com/kennethreitz-archive/gitx.git
synced 2026-06-05 23:40:18 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -14,7 +14,7 @@
|
||||
|
||||
@implementation PBGitRepository
|
||||
|
||||
@synthesize path;
|
||||
@synthesize path, revisionList;
|
||||
static NSString* gitPath;
|
||||
|
||||
+ (void) initialize
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user