mirror of
https://github.com/kennethreitz-archive/gitx.git
synced 2026-06-05 23:40:18 +00:00
Rewrite the graphing code
This uses more Cocoa classes to draw the lines, making it easier to understand and hopefully maintain. Furthermore, we use less memory now, which is nice, but all the dynamic arrays probably mean more CPU usage.
This commit is contained in:
@@ -29,6 +29,8 @@
|
||||
F56526240E03D85900F03B52 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F56526230E03D85900F03B52 /* WebKit.framework */; };
|
||||
F565262B0E03D89B00F03B52 /* PBWebGitController.m in Sources */ = {isa = PBXBuildFile; fileRef = F565262A0E03D89B00F03B52 /* PBWebGitController.m */; };
|
||||
F565265A0E03E71B00F03B52 /* commit.html in Resources */ = {isa = PBXBuildFile; fileRef = F56526590E03E71B00F03B52 /* commit.html */; };
|
||||
F56CC7290E65E0AD004307B4 /* PBLine.m in Sources */ = {isa = PBXBuildFile; fileRef = F56CC7280E65E0AD004307B4 /* PBLine.m */; };
|
||||
F56CC7320E65E0E5004307B4 /* PBGraphCellInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = F56CC7310E65E0E5004307B4 /* PBGraphCellInfo.m */; };
|
||||
F57ABE0B0E0442DD00A088B8 /* commit.js in Resources */ = {isa = PBXBuildFile; fileRef = F57ABDDE0E0441DE00A088B8 /* commit.js */; };
|
||||
F57ABE2B0E04435100A088B8 /* prototype.js in Resources */ = {isa = PBXBuildFile; fileRef = F57ABE180E04431D00A088B8 /* prototype.js */; };
|
||||
F57CC3910E05DDF2000472E2 /* PBEasyPipe.m in Sources */ = {isa = PBXBuildFile; fileRef = F57CC3900E05DDF2000472E2 /* PBEasyPipe.m */; };
|
||||
@@ -90,6 +92,10 @@
|
||||
F56526290E03D89B00F03B52 /* PBWebGitController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBWebGitController.h; sourceTree = "<group>"; };
|
||||
F565262A0E03D89B00F03B52 /* PBWebGitController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBWebGitController.m; sourceTree = "<group>"; };
|
||||
F56526590E03E71B00F03B52 /* commit.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = commit.html; path = html/commit.html; sourceTree = "<group>"; };
|
||||
F56CC7270E65E0AD004307B4 /* PBLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBLine.h; sourceTree = "<group>"; };
|
||||
F56CC7280E65E0AD004307B4 /* PBLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBLine.m; sourceTree = "<group>"; };
|
||||
F56CC7300E65E0E5004307B4 /* PBGraphCellInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGraphCellInfo.h; sourceTree = "<group>"; };
|
||||
F56CC7310E65E0E5004307B4 /* PBGraphCellInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGraphCellInfo.m; sourceTree = "<group>"; };
|
||||
F57ABDDE0E0441DE00A088B8 /* commit.js */ = {isa = PBXFileReference; explicitFileType = sourcecode.javascript; fileEncoding = 4; name = commit.js; path = html/commit.js; sourceTree = "<group>"; };
|
||||
F57ABE180E04431D00A088B8 /* prototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = prototype.js; path = html/prototype.js; sourceTree = "<group>"; };
|
||||
F57CC38F0E05DDF2000472E2 /* PBEasyPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBEasyPipe.h; sourceTree = "<group>"; };
|
||||
@@ -232,6 +238,8 @@
|
||||
F56174540E05887E001DCD79 /* Git */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F56CC7300E65E0E5004307B4 /* PBGraphCellInfo.h */,
|
||||
F56CC7310E65E0E5004307B4 /* PBGraphCellInfo.m */,
|
||||
F5FF4E780E082E440006317A /* PBGitGrapher.h */,
|
||||
F5FF4E790E082E440006317A /* PBGitGrapher.m */,
|
||||
F5945E150E02B0C200706420 /* PBGitRepository.h */,
|
||||
@@ -277,6 +285,8 @@
|
||||
F513085A0E0740F2000C8BCD /* PBQLOutlineView.m */,
|
||||
F50FE0E10E07BE9600854FCD /* PBGitRevisionCell.h */,
|
||||
F50FE0E20E07BE9600854FCD /* PBGitRevisionCell.m */,
|
||||
F56CC7270E65E0AD004307B4 /* PBLine.h */,
|
||||
F56CC7280E65E0AD004307B4 /* PBLine.m */,
|
||||
);
|
||||
name = Aux;
|
||||
sourceTree = "<group>";
|
||||
@@ -393,6 +403,8 @@
|
||||
F5FF4E7A0E082E440006317A /* PBGitGrapher.m in Sources */,
|
||||
911111F80E594F3F00BF76B4 /* PBRepositoryDocumentController.m in Sources */,
|
||||
913D5E5F0E556A9300CECEA2 /* PBCLIProxy.mm in Sources */,
|
||||
F56CC7290E65E0AD004307B4 /* PBLine.m in Sources */,
|
||||
F56CC7320E65E0E5004307B4 /* PBGraphCellInfo.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
+4
-18
@@ -8,7 +8,8 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "PBGitCommit.h"
|
||||
|
||||
#import "PBLine.h"
|
||||
#import "PBGraphCellInfo.h"
|
||||
|
||||
struct PBGitGraphColumn {
|
||||
NSString* commit; // Commit that we're looking for
|
||||
@@ -18,25 +19,10 @@ struct PBGitGraphColumn {
|
||||
|
||||
#define PBGitMaxColumns 100
|
||||
|
||||
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;
|
||||
NSMutableArray* cellsInfo;
|
||||
}
|
||||
|
||||
- (void) parseCommits: (NSArray *) array;
|
||||
- (struct PBGitGraphCellInfo) cellInfoForRow: (int) row;
|
||||
- (PBGraphCellInfo*) cellInfoForRow: (int) row;
|
||||
@end
|
||||
|
||||
+52
-56
@@ -14,73 +14,67 @@
|
||||
|
||||
- (void) parseCommits: (NSArray *) commits
|
||||
{
|
||||
cellsInfo = malloc(sizeof(struct PBGitGraphCellInfo) * [commits count]);
|
||||
memset(cellsInfo, 0, sizeof(struct PBGitGraphCellInfo) * [commits count]);
|
||||
|
||||
cellsInfo = [NSMutableArray arrayWithCapacity: [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;
|
||||
PBGraphCellInfo* previous;
|
||||
NSMutableArray* previousLanes = [NSMutableArray array];
|
||||
|
||||
for (PBGitCommit* commit in commits) {
|
||||
int i = 0, newPos = -1;
|
||||
for (i = 0; i < PBGitMaxColumns; i++) {
|
||||
info->lowerMapping[i] = -1;
|
||||
info->upperMapping[i] = -1;
|
||||
}
|
||||
|
||||
NSMutableArray* currentLanes = [NSMutableArray array];
|
||||
NSMutableArray* lines = [NSMutableArray array];
|
||||
BOOL didFirst = NO;
|
||||
|
||||
// First, iterate over earlier columns and pass through any that don't want this commit
|
||||
if (previous != nil) {
|
||||
|
||||
// We can't count until numColumns here, as it's only used for the width of the cell.
|
||||
for (i = 0; i < PBGitMaxColumns; i++) {
|
||||
if ((previous->columns[i].commit) == nil)
|
||||
continue;
|
||||
|
||||
for (NSString* lane in previousLanes) {
|
||||
i++;
|
||||
// This is our commit! We should do a "merge": move the line from
|
||||
// our upperMapping to their lowerMapping
|
||||
if ([previous->columns[i].commit isEqualToString:info->commit]) {
|
||||
if ([lane isEqualToString:commit.sha]) {
|
||||
if (!didFirst) {
|
||||
didFirst = YES;
|
||||
info->position = info->numColumns++;
|
||||
info->columns[info->position].commit = [commit.parents objectAtIndex:0];
|
||||
[currentLanes addObject: [commit.parents objectAtIndex:0]];
|
||||
newPos = [currentLanes count];
|
||||
}
|
||||
newPos = info->position;
|
||||
info->upperMapping[i] = newPos;
|
||||
[lines addObject: [PBLine upperLineFrom: i to: newPos]];
|
||||
}
|
||||
else {
|
||||
// We are not this commit.
|
||||
// Try to find an earlier column for this commit.
|
||||
int j;
|
||||
int j = 0;
|
||||
BOOL found = NO;
|
||||
for (j = 0; j < info->numColumns; j++) {
|
||||
if (j == info->position)
|
||||
for (NSString* column in currentLanes) {
|
||||
j++;
|
||||
// ??? what is this?
|
||||
if (j == newPos)
|
||||
continue;
|
||||
if ([previous->columns[i].commit isEqualToString: info->columns[j].commit]) {
|
||||
if ([column isEqualToString: lane]) {
|
||||
// We already have a column for this commit. use it instead
|
||||
newPos = j;
|
||||
info->upperMapping[previous->lowerMapping[i]] = newPos;
|
||||
[lines addObject: [PBLine lowerLineFrom: i to: j]];
|
||||
found = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We need a new column for this.
|
||||
if (!found) {
|
||||
|
||||
if (previous->columns[i].color == 10)
|
||||
continue;
|
||||
// This was used as a hack to stop large lanes from drawing
|
||||
//if (previous->columns[i].color == 10)
|
||||
// continue;
|
||||
|
||||
newPos = info->numColumns++;
|
||||
info->columns[newPos] = previous->columns[i];
|
||||
info->columns[newPos].color++;
|
||||
info->upperMapping[newPos] = newPos;
|
||||
[currentLanes addObject: lane];
|
||||
[lines addObject: [PBLine upperLineFrom: [currentLanes count] to: [currentLanes count]]];
|
||||
[lines addObject: [PBLine lowerLineFrom: [currentLanes count] to: [currentLanes count]]];
|
||||
}
|
||||
}
|
||||
// For existing columns, we always just continue straight down
|
||||
info->lowerMapping[newPos] = newPos;
|
||||
// ^^ I don't know what that means anymore :(
|
||||
[lines addObject:[PBLine lowerLineFrom:newPos to:newPos]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,9 +82,9 @@
|
||||
|
||||
// If we already did the first parent, don't do so again
|
||||
if (!didFirst) {
|
||||
info->position = info->numColumns++;
|
||||
info->columns[info->position].commit = [commit.parents objectAtIndex:0];
|
||||
info->lowerMapping[info->position] = info->position;
|
||||
[currentLanes addObject: [commit.parents objectAtIndex:0]];
|
||||
newPos = [currentLanes count];
|
||||
[lines addObject:[PBLine lowerLineFrom: newPos to: newPos]];
|
||||
}
|
||||
|
||||
// Add all other parents
|
||||
@@ -100,39 +94,41 @@
|
||||
BOOL addedParent = NO;
|
||||
|
||||
for (NSString* parent in [commit.parents subarrayWithRange:NSMakeRange(1, [commit.parents count] -1)]) {
|
||||
int i;
|
||||
int i = 0;
|
||||
BOOL was_displayed = NO;
|
||||
for (i = 0; i < info->numColumns; i++)
|
||||
if ([info->columns[i].commit isEqualToString: parent]) {
|
||||
// TODO!
|
||||
// !!! BUG
|
||||
// This overwrites an existing mapping.
|
||||
// We should instead have the possibility
|
||||
// to add multiple lower mappings
|
||||
// As we don't have that now, pieces of the graph are missing
|
||||
info->lowerMapping[i] = info->position;
|
||||
for (NSString* column in currentLanes) {
|
||||
i++;
|
||||
if ([column isEqualToString: parent]) {
|
||||
[lines addObject:[PBLine lowerLineFrom: i to: newPos]];
|
||||
was_displayed = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (was_displayed)
|
||||
continue;
|
||||
|
||||
// Really add this parent
|
||||
addedParent = YES;
|
||||
info->columns[info->numColumns++].commit = parent;
|
||||
info->lowerMapping[info->numColumns -1] = info->position;
|
||||
[currentLanes addObject:parent];
|
||||
[lines addObject:[PBLine lowerLineFrom: [currentLanes count] to: newPos]];
|
||||
}
|
||||
|
||||
// A parent was added, so we have room to not indent.
|
||||
if (addedParent)
|
||||
info->numColumns--;
|
||||
previous = info;
|
||||
++row;
|
||||
previous = [[PBGraphCellInfo alloc] initWithPosition:newPos andLines:lines];
|
||||
|
||||
// If a parent was added, we have room to not indent.
|
||||
if (addedParent)
|
||||
previous.numColumns = [currentLanes count] - 1;
|
||||
else
|
||||
previous.numColumns = [currentLanes count];
|
||||
previousLanes = currentLanes;
|
||||
[cellsInfo addObject: previous];
|
||||
}
|
||||
}
|
||||
- (struct PBGitGraphCellInfo) cellInfoForRow: (int) row
|
||||
|
||||
- (PBGraphCellInfo*) cellInfoForRow: (int) row
|
||||
{
|
||||
return cellsInfo[row];
|
||||
return [cellsInfo objectAtIndex: row];
|
||||
}
|
||||
|
||||
- (void) finalize
|
||||
|
||||
+2
-2
@@ -10,9 +10,9 @@
|
||||
#import "PBGitGrapher.h"
|
||||
|
||||
@interface PBGitRevisionCell : NSTextFieldCell {
|
||||
PBGitCellInfo cellInfo;
|
||||
PBGraphCellInfo* cellInfo;
|
||||
BOOL isReady;
|
||||
}
|
||||
|
||||
@property(assign) PBGitCellInfo cellInfo;
|
||||
@property(assign) PBGraphCellInfo* cellInfo;
|
||||
@end
|
||||
|
||||
+8
-11
@@ -12,7 +12,7 @@
|
||||
@implementation PBGitRevisionCell
|
||||
|
||||
@synthesize cellInfo;
|
||||
-(void) setCellInfo: (PBGitCellInfo) info
|
||||
-(void) setCellInfo: (PBGraphCellInfo*) info
|
||||
{
|
||||
isReady = YES;
|
||||
cellInfo = info;
|
||||
@@ -68,7 +68,7 @@
|
||||
|
||||
NSBezierPath * path = [NSBezierPath bezierPath];
|
||||
path = [NSBezierPath bezierPathWithOvalInRect:oval];
|
||||
[[col objectAtIndex:cellInfo.columns[c].color] set];
|
||||
//[[col objectAtIndex:cellInfo.columns[c].color] set];
|
||||
[path fill];
|
||||
|
||||
NSRect smallOval = { columnOrigin.x - 3, columnOrigin.y + r.size.height * 0.5 - 3, 6, 6};
|
||||
@@ -90,16 +90,13 @@
|
||||
// Adjust by removing the border
|
||||
ownRect.size.height += 2;
|
||||
ownRect.origin.y -= 1;
|
||||
ownRect.origin.x += 10;
|
||||
|
||||
int column = 0;
|
||||
ownRect.origin.x += 0;
|
||||
|
||||
// We can't iterate over numColumns here, as there may be connections to be drawn outside our columns.
|
||||
for (column = 0; column < PBGitMaxColumns; column++) {
|
||||
if (cellInfo.upperMapping[column] !=-1)
|
||||
[self drawLineFromColumn:column toColumn: cellInfo.upperMapping[column] inRect:ownRect offset: 0];
|
||||
if (cellInfo.lowerMapping[column] !=-1)
|
||||
[self drawLineFromColumn: column toColumn: cellInfo.lowerMapping[column] inRect:ownRect offset: ownRect.size.height];
|
||||
for (PBLine* line in cellInfo.lines) {
|
||||
if (line.upper == 0)
|
||||
[self drawLineFromColumn: line.from toColumn: line.to inRect:ownRect offset: ownRect.size.height];
|
||||
else
|
||||
[self drawLineFromColumn:line.from toColumn: line.to inRect:ownRect offset: 0];
|
||||
}
|
||||
|
||||
[self drawCircleForColumn: cellInfo.position inRect: ownRect];
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// PBGraphCellInfo.h
|
||||
// GitX
|
||||
//
|
||||
// Created by Pieter de Bie on 27-08-08.
|
||||
// Copyright 2008 __MyCompanyName__. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
|
||||
@interface PBGraphCellInfo : NSObject
|
||||
{
|
||||
int position;
|
||||
NSArray* lines;
|
||||
int numColumns;
|
||||
}
|
||||
@property(readonly) NSArray* lines;
|
||||
@property(assign) int position, numColumns;
|
||||
|
||||
- (id)initWithPosition: (int) p andLines: (NSArray*) l;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// PBGraphCellInfo.m
|
||||
// GitX
|
||||
//
|
||||
// Created by Pieter de Bie on 27-08-08.
|
||||
// Copyright 2008 __MyCompanyName__. All rights reserved.
|
||||
//
|
||||
|
||||
#import "PBGraphCellInfo.h"
|
||||
|
||||
|
||||
@implementation PBGraphCellInfo
|
||||
@synthesize lines, position, numColumns;
|
||||
- (id)initWithPosition: (int) p andLines: (NSArray*) l
|
||||
{
|
||||
position = p;
|
||||
lines = l;
|
||||
|
||||
return self;
|
||||
}
|
||||
@end
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// PBLine.h
|
||||
// GitX
|
||||
//
|
||||
// Created by Pieter de Bie on 27-08-08.
|
||||
// Copyright 2008 __MyCompanyName__. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
|
||||
@interface PBLine : NSObject
|
||||
{
|
||||
int upper;
|
||||
int from;
|
||||
int to;
|
||||
}
|
||||
@property(readonly) int upper, from, to;
|
||||
- (id)initWithUpper: (int) u From: (int) f to: (int) t;
|
||||
+ (PBLine*) lowerLineFrom:(int) f to: (int) t;
|
||||
+ (PBLine*) upperLineFrom:(int) f to: (int) t;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// PBLine.m
|
||||
// GitX
|
||||
//
|
||||
// Created by Pieter de Bie on 27-08-08.
|
||||
// Copyright 2008 __MyCompanyName__. All rights reserved.
|
||||
//
|
||||
|
||||
#import "PBLine.h"
|
||||
|
||||
|
||||
@implementation PBLine
|
||||
@synthesize upper, from, to;
|
||||
- (id)initWithUpper: (int) u From: (int) f to: (int) t;
|
||||
{
|
||||
upper = u;
|
||||
from = f;
|
||||
to = t;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (PBLine*) lowerLineFrom:(int) f to: (int) t
|
||||
{
|
||||
return [[PBLine alloc] initWithUpper:0 From:f to:t];
|
||||
}
|
||||
|
||||
+ (PBLine*) upperLineFrom:(int) f to: (int) t
|
||||
{
|
||||
return [[PBLine alloc] initWithUpper:1 From:f to:t];
|
||||
}
|
||||
@end
|
||||
Reference in New Issue
Block a user