mirror of
https://github.com/pcottle/learnGitBranching.git
synced 2025-06-27 00:18:56 +02:00
have HEAD working
This commit is contained in:
parent
3b58cf2912
commit
f78e77e5c6
4 changed files with 116 additions and 29 deletions
|
@ -18,9 +18,12 @@ var GRAPHICS = {
|
||||||
curveControlPointOffset: 50,
|
curveControlPointOffset: 50,
|
||||||
defaultEasing: 'easeInOut',
|
defaultEasing: 'easeInOut',
|
||||||
defaultAnimationTime: 300,
|
defaultAnimationTime: 300,
|
||||||
|
|
||||||
rectFill: '#FF3A3A',
|
rectFill: '#FF3A3A',
|
||||||
|
headRectFill: '#2831FF',
|
||||||
rectStroke: '#FFF',
|
rectStroke: '#FFF',
|
||||||
rectStrokeWidth: '3',
|
rectStrokeWidth: '3',
|
||||||
|
|
||||||
multiBranchY: 20,
|
multiBranchY: 20,
|
||||||
upstreamHeadOpacity: 0.5,
|
upstreamHeadOpacity: 0.5,
|
||||||
upstreamNoneOpacity: 0.2,
|
upstreamNoneOpacity: 0.2,
|
||||||
|
|
|
@ -40,6 +40,9 @@ GitEngine.prototype.init = function() {
|
||||||
|
|
||||||
// commit once to get things going
|
// commit once to get things going
|
||||||
this.commit();
|
this.commit();
|
||||||
|
|
||||||
|
// now we are ready
|
||||||
|
events.trigger('gitEngineReady', this);
|
||||||
};
|
};
|
||||||
|
|
||||||
GitEngine.prototype.getDetachedHead = function() {
|
GitEngine.prototype.getDetachedHead = function() {
|
||||||
|
|
116
src/tree.js
116
src/tree.js
|
@ -4,6 +4,12 @@ var VisBranch = Backbone.Model.extend({
|
||||||
text: null,
|
text: null,
|
||||||
rect: null,
|
rect: null,
|
||||||
arrow: null,
|
arrow: null,
|
||||||
|
isHead: false,
|
||||||
|
flip: 1,
|
||||||
|
|
||||||
|
fill: GRAPHICS.rectFill,
|
||||||
|
stroke: GRAPHICS.rectStroke,
|
||||||
|
|
||||||
offsetX: GRAPHICS.nodeRadius * 4.75,
|
offsetX: GRAPHICS.nodeRadius * 4.75,
|
||||||
offsetY: 0,
|
offsetY: 0,
|
||||||
arrowHeight: 14,
|
arrowHeight: 14,
|
||||||
|
@ -11,8 +17,10 @@ var VisBranch = Backbone.Model.extend({
|
||||||
arrowEdgeHeight: 6,
|
arrowEdgeHeight: 6,
|
||||||
arrowLength: 14,
|
arrowLength: 14,
|
||||||
arrowOffsetFromCircleX: 10,
|
arrowOffsetFromCircleX: 10,
|
||||||
|
|
||||||
vPad: 5,
|
vPad: 5,
|
||||||
hPad: 5,
|
hPad: 5,
|
||||||
|
|
||||||
animationSpeed: GRAPHICS.defaultAnimationTime,
|
animationSpeed: GRAPHICS.defaultAnimationTime,
|
||||||
animationEasing: GRAPHICS.defaultEasing
|
animationEasing: GRAPHICS.defaultEasing
|
||||||
},
|
},
|
||||||
|
@ -25,15 +33,27 @@ var VisBranch = Backbone.Model.extend({
|
||||||
|
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
this.validateAtInit();
|
this.validateAtInit();
|
||||||
|
if (this.get('branch').get('id') == 'HEAD') {
|
||||||
|
// switch to a head ref
|
||||||
|
this.set('isHead', true);
|
||||||
|
this.set('flip', -1);
|
||||||
|
|
||||||
|
this.set('fill', GRAPHICS.headRectFill);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getCommitPosition: function() {
|
getCommitPosition: function() {
|
||||||
var commit = this.get('branch').get('target');
|
var commit = gitEngine.getCommitFromRef(this.get('branch'));
|
||||||
var visNode = commit.get('visNode');
|
var visNode = commit.get('visNode');
|
||||||
return visNode.getScreenCoords();
|
return visNode.getScreenCoords();
|
||||||
},
|
},
|
||||||
|
|
||||||
getBranchStackIndex: function() {
|
getBranchStackIndex: function() {
|
||||||
|
if (this.get('isHead')) {
|
||||||
|
// head is never stacked with other branches
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
var myArray = this.getBranchStackArray();
|
var myArray = this.getBranchStackArray();
|
||||||
var index = -1;
|
var index = -1;
|
||||||
_.each(myArray, function(branch, i) {
|
_.each(myArray, function(branch, i) {
|
||||||
|
@ -45,11 +65,23 @@ var VisBranch = Backbone.Model.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
getBranchStackLength: function() {
|
getBranchStackLength: function() {
|
||||||
|
if (this.get('isHead')) {
|
||||||
|
// head is always by itself
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return this.getBranchStackArray().length;
|
return this.getBranchStackArray().length;
|
||||||
},
|
},
|
||||||
|
|
||||||
getBranchStackArray: function() {
|
getBranchStackArray: function() {
|
||||||
return gitVisuals.branchStackMap[this.get('branch').get('target').get('id')];
|
var arr = gitVisuals.branchStackMap[this.get('branch').get('target').get('id')];
|
||||||
|
if (arr === undefined) {
|
||||||
|
// this only occurs when we are generating graphics inside of
|
||||||
|
// a new Branch instantiation, so we need to force the update
|
||||||
|
gitVisuals.calcBranchStacks();
|
||||||
|
return this.getBranchStackArray();
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
},
|
},
|
||||||
|
|
||||||
getTextPosition: function() {
|
getTextPosition: function() {
|
||||||
|
@ -59,13 +91,14 @@ var VisBranch = Backbone.Model.extend({
|
||||||
// so everything is independent
|
// so everything is independent
|
||||||
var myPos = this.getBranchStackIndex();
|
var myPos = this.getBranchStackIndex();
|
||||||
return {
|
return {
|
||||||
x: pos.x + this.get('offsetX'),
|
x: pos.x + this.get('flip') * this.get('offsetX'),
|
||||||
y: pos.y + myPos * GRAPHICS.multiBranchY + this.get('offsetY')
|
y: pos.y + myPos * GRAPHICS.multiBranchY + this.get('offsetY')
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
getRectPosition: function() {
|
getRectPosition: function() {
|
||||||
var pos = this.getTextPosition();
|
var pos = this.getTextPosition();
|
||||||
|
var f = this.get('flip');
|
||||||
// first get text width and height
|
// first get text width and height
|
||||||
var textSize = this.getTextSize();
|
var textSize = this.getTextSize();
|
||||||
return {
|
return {
|
||||||
|
@ -85,26 +118,27 @@ var VisBranch = Backbone.Model.extend({
|
||||||
var toStringCoords = function(pos) {
|
var toStringCoords = function(pos) {
|
||||||
return String(Math.round(pos.x)) + ',' + String(Math.round(pos.y));
|
return String(Math.round(pos.x)) + ',' + String(Math.round(pos.y));
|
||||||
};
|
};
|
||||||
|
var f = this.get('flip');
|
||||||
|
|
||||||
var arrowTip = offset2d(this.getCommitPosition(),
|
var arrowTip = offset2d(this.getCommitPosition(),
|
||||||
this.get('arrowOffsetFromCircleX'),
|
f * this.get('arrowOffsetFromCircleX'),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
var arrowEdgeUp = offset2d(arrowTip, this.get('arrowLength'), -this.get('arrowHeight'));
|
var arrowEdgeUp = offset2d(arrowTip, f * this.get('arrowLength'), -this.get('arrowHeight'));
|
||||||
var arrowEdgeLow = offset2d(arrowTip, this.get('arrowLength'), this.get('arrowHeight'));
|
var arrowEdgeLow = offset2d(arrowTip, f * this.get('arrowLength'), this.get('arrowHeight'));
|
||||||
|
|
||||||
var arrowInnerUp = offset2d(arrowEdgeUp,
|
var arrowInnerUp = offset2d(arrowEdgeUp,
|
||||||
this.get('arrowInnerSkew'),
|
f * this.get('arrowInnerSkew'),
|
||||||
this.get('arrowEdgeHeight')
|
this.get('arrowEdgeHeight')
|
||||||
);
|
);
|
||||||
var arrowInnerLow = offset2d(arrowEdgeLow,
|
var arrowInnerLow = offset2d(arrowEdgeLow,
|
||||||
this.get('arrowInnerSkew'),
|
f * this.get('arrowInnerSkew'),
|
||||||
-this.get('arrowEdgeHeight')
|
-this.get('arrowEdgeHeight')
|
||||||
);
|
);
|
||||||
|
|
||||||
var tailLength = 30;
|
var tailLength = 30;
|
||||||
var arrowStartUp = offset2d(arrowInnerUp, tailLength, 0);
|
var arrowStartUp = offset2d(arrowInnerUp, f * tailLength, 0);
|
||||||
var arrowStartLow = offset2d(arrowInnerLow, tailLength, 0);
|
var arrowStartLow = offset2d(arrowInnerLow, f * tailLength, 0);
|
||||||
|
|
||||||
var pathStr = '';
|
var pathStr = '';
|
||||||
pathStr += 'M' + toStringCoords(arrowStartUp) + ' ';
|
pathStr += 'M' + toStringCoords(arrowStartUp) + ' ';
|
||||||
|
@ -130,6 +164,13 @@ var VisBranch = Backbone.Model.extend({
|
||||||
};
|
};
|
||||||
|
|
||||||
var textNode = this.get('text').node;
|
var textNode = this.get('text').node;
|
||||||
|
if (this.get('isHead')) {
|
||||||
|
// HEAD is a special case
|
||||||
|
return {
|
||||||
|
w: textNode.clientWidth,
|
||||||
|
h: textNode.clientHeight
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
var maxWidth = 0;
|
var maxWidth = 0;
|
||||||
_.each(this.getBranchStackArray(), function(branch) {
|
_.each(this.getBranchStackArray(), function(branch) {
|
||||||
|
@ -192,7 +233,8 @@ var VisBranch = Backbone.Model.extend({
|
||||||
var text = paper.text(textPos.x, textPos.y, String(name));
|
var text = paper.text(textPos.x, textPos.y, String(name));
|
||||||
text.attr({
|
text.attr({
|
||||||
'font-size': 14,
|
'font-size': 14,
|
||||||
'font-family': 'Monaco, Courier, font-monospace'
|
'font-family': 'Monaco, Courier, font-monospace',
|
||||||
|
opacity: this.getTextOpacity()
|
||||||
});
|
});
|
||||||
this.set('text', text);
|
this.set('text', text);
|
||||||
|
|
||||||
|
@ -200,18 +242,20 @@ var VisBranch = Backbone.Model.extend({
|
||||||
var sizeOfRect = this.getRectSize();
|
var sizeOfRect = this.getRectSize();
|
||||||
var rect = paper.rect(rectPos.x, rectPos.y, sizeOfRect.w, sizeOfRect.h, 8);
|
var rect = paper.rect(rectPos.x, rectPos.y, sizeOfRect.w, sizeOfRect.h, 8);
|
||||||
rect.attr({
|
rect.attr({
|
||||||
fill: GRAPHICS.rectFill,
|
fill: this.get('fill'),
|
||||||
stroke: GRAPHICS.rectStroke,
|
stroke: this.get('stroke'),
|
||||||
'stroke-width': GRAPHICS.rectStrokeWidth
|
'stroke-width': GRAPHICS.rectStrokeWidth,
|
||||||
|
opacity: this.getNonTextOpacity()
|
||||||
});
|
});
|
||||||
this.set('rect', rect);
|
this.set('rect', rect);
|
||||||
|
|
||||||
var arrowPath = this.getArrowPath();
|
var arrowPath = this.getArrowPath();
|
||||||
var arrow = paper.path(arrowPath);
|
var arrow = paper.path(arrowPath);
|
||||||
arrow.attr({
|
arrow.attr({
|
||||||
fill: GRAPHICS.rectFill,
|
fill: this.get('fill'),
|
||||||
stroke: GRAPHICS.rectStroke,
|
stroke: this.get('stroke'),
|
||||||
'stroke-width': GRAPHICS.rectStrokeWidth
|
'stroke-width': GRAPHICS.rectStrokeWidth,
|
||||||
|
opacity: this.getNonTextOpacity()
|
||||||
});
|
});
|
||||||
this.set('arrow', arrow);
|
this.set('arrow', arrow);
|
||||||
|
|
||||||
|
@ -225,16 +269,32 @@ var VisBranch = Backbone.Model.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getNonTextOpacity: function() {
|
||||||
|
if (this.get('isHead')) {
|
||||||
|
return gitEngine.getDetachedHead() ? 1 : 0;
|
||||||
|
}
|
||||||
|
return this.getBranchStackIndex() == 0 ? 1 : 0.0;
|
||||||
|
},
|
||||||
|
|
||||||
|
getTextOpacity: function() {
|
||||||
|
if (this.get('isHead')) {
|
||||||
|
return gitEngine.getDetachedHead() ? 1 : 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
|
||||||
animateUpdatedPos: function(speed, easing) {
|
animateUpdatedPos: function(speed, easing) {
|
||||||
var s = speed !== undefined ? speed : this.get('animationSpeed');
|
var s = speed !== undefined ? speed : this.get('animationSpeed');
|
||||||
var e = easing || this.get('animationEasing');
|
var e = easing || this.get('animationEasing');
|
||||||
var masterOpacity = this.getBranchStackIndex() == 0 ? 1 : 0.0;
|
var nonTextOpacity = this.getNonTextOpacity();
|
||||||
|
var textOpacity = this.getTextOpacity();
|
||||||
|
|
||||||
this.updateName();
|
this.updateName();
|
||||||
var textPos = this.getTextPosition();
|
var textPos = this.getTextPosition();
|
||||||
this.get('text').stop().animate({
|
this.get('text').stop().animate({
|
||||||
x: textPos.x,
|
x: textPos.x,
|
||||||
y: textPos.y
|
y: textPos.y,
|
||||||
|
opacity: textOpacity
|
||||||
}, s, e);
|
}, s, e);
|
||||||
|
|
||||||
var rectPos = this.getRectPosition();
|
var rectPos = this.getRectPosition();
|
||||||
|
@ -244,13 +304,13 @@ var VisBranch = Backbone.Model.extend({
|
||||||
y: rectPos.y,
|
y: rectPos.y,
|
||||||
width: rectSize.w,
|
width: rectSize.w,
|
||||||
height: rectSize.h,
|
height: rectSize.h,
|
||||||
opacity: masterOpacity,
|
opacity: nonTextOpacity,
|
||||||
}, s, e);
|
}, s, e);
|
||||||
|
|
||||||
var arrowPath = this.getArrowPath();
|
var arrowPath = this.getArrowPath();
|
||||||
this.get('arrow').stop().animate({
|
this.get('arrow').stop().animate({
|
||||||
path: arrowPath,
|
path: arrowPath,
|
||||||
opacity: masterOpacity
|
opacity: nonTextOpacity
|
||||||
}, s, e);
|
}, s, e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -259,6 +319,7 @@ var VisBranch = Backbone.Model.extend({
|
||||||
var VisNode = Backbone.Model.extend({
|
var VisNode = Backbone.Model.extend({
|
||||||
defaults: {
|
defaults: {
|
||||||
depth: undefined,
|
depth: undefined,
|
||||||
|
maxWidth: null,
|
||||||
id: null,
|
id: null,
|
||||||
pos: null,
|
pos: null,
|
||||||
radius: null,
|
radius: null,
|
||||||
|
@ -295,6 +356,19 @@ var VisNode = Backbone.Model.extend({
|
||||||
pos.y = this.get('depth') * depthIncrement;
|
pos.y = this.get('depth') * depthIncrement;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getMaxWidthScaled: function() {
|
||||||
|
// returns our max width scaled based on if we are visible
|
||||||
|
// from a branch or not
|
||||||
|
var stat = gitVisuals.getCommitUpstreamStatus(this.get('commit'));
|
||||||
|
var map = {
|
||||||
|
branch: 1,
|
||||||
|
head: 0.3,
|
||||||
|
none: 0.1
|
||||||
|
};
|
||||||
|
if (map[stat] === undefined) { throw new Error('bad stat'); }
|
||||||
|
return map[stat] * this.get('maxWidth');
|
||||||
|
},
|
||||||
|
|
||||||
toFront: function() {
|
toFront: function() {
|
||||||
this.get('circle').toFront();
|
this.get('circle').toFront();
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,8 +5,8 @@ function GitVisuals(options) {
|
||||||
|
|
||||||
this.edgeCollection = new VisEdgeCollection();
|
this.edgeCollection = new VisEdgeCollection();
|
||||||
this.visBranchCollection = new VisBranchCollection();
|
this.visBranchCollection = new VisBranchCollection();
|
||||||
|
|
||||||
this.commitMap = {};
|
this.commitMap = {};
|
||||||
|
|
||||||
this.rootCommit = null;
|
this.rootCommit = null;
|
||||||
this.branchStackMap = null;
|
this.branchStackMap = null;
|
||||||
this.upstreamBranchSet = null;
|
this.upstreamBranchSet = null;
|
||||||
|
@ -30,8 +30,16 @@ function GitVisuals(options) {
|
||||||
events.on('refreshTree', _.bind(
|
events.on('refreshTree', _.bind(
|
||||||
this.refreshTree, this
|
this.refreshTree, this
|
||||||
));
|
));
|
||||||
|
events.on('gitEngineReady', this.whenGitEngineReady, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GitVisuals.prototype.whenGitEngineReady = function(gitEngine) {
|
||||||
|
// seed this with the HEAD pseudo-branch
|
||||||
|
this.visBranchCollection.add(new VisBranch({
|
||||||
|
branch: gitEngine.HEAD
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
GitVisuals.prototype.getScreenBounds = function() {
|
GitVisuals.prototype.getScreenBounds = function() {
|
||||||
// for now we return the node radius subtracted from the walls
|
// for now we return the node radius subtracted from the walls
|
||||||
return {
|
return {
|
||||||
|
@ -57,7 +65,7 @@ GitVisuals.prototype.toScreenCoords = function(pos) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
== Tree Calculation Parts ==
|
== BEGIN Tree Calculation Parts ==
|
||||||
_ __ __ _
|
_ __ __ _
|
||||||
\\/ / \ \//_
|
\\/ / \ \//_
|
||||||
\ \ / __| __
|
\ \ / __| __
|
||||||
|
@ -101,11 +109,11 @@ GitVisuals.prototype.calcTreeCoords = function() {
|
||||||
throw new Error('grr, no root commit!');
|
throw new Error('grr, no root commit!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.calcUpstreamSets();
|
||||||
|
this.calcBranchStacks();
|
||||||
|
|
||||||
this.calcDepth();
|
this.calcDepth();
|
||||||
this.calcWidth();
|
this.calcWidth();
|
||||||
|
|
||||||
this.calcBranchStacks();
|
|
||||||
this.calcUpstreamSets();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
GitVisuals.prototype.calcGraphicsCoords = function() {
|
GitVisuals.prototype.calcGraphicsCoords = function() {
|
||||||
|
@ -116,7 +124,6 @@ GitVisuals.prototype.calcGraphicsCoords = function() {
|
||||||
|
|
||||||
GitVisuals.prototype.calcUpstreamSets = function() {
|
GitVisuals.prototype.calcUpstreamSets = function() {
|
||||||
this.upstreamBranchSet = gitEngine.getUpstreamBranchSet();
|
this.upstreamBranchSet = gitEngine.getUpstreamBranchSet();
|
||||||
|
|
||||||
this.upstreamHeadSet = gitEngine.getUpstreamHeadSet();
|
this.upstreamHeadSet = gitEngine.getUpstreamHeadSet();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -193,7 +200,7 @@ GitVisuals.prototype.assignBoundsRecursive = function(commit, min, max) {
|
||||||
var totalFlex = 0;
|
var totalFlex = 0;
|
||||||
var children = commit.get('children');
|
var children = commit.get('children');
|
||||||
_.each(children, function(child) {
|
_.each(children, function(child) {
|
||||||
totalFlex += child.get('visNode').get('maxWidth');
|
totalFlex += child.get('visNode').getMaxWidthScaled();
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
var prevBound = min;
|
var prevBound = min;
|
||||||
|
@ -201,7 +208,7 @@ GitVisuals.prototype.assignBoundsRecursive = function(commit, min, max) {
|
||||||
// now go through and do everything
|
// now go through and do everything
|
||||||
// TODO: order so the max width children are in the middle!!
|
// TODO: order so the max width children are in the middle!!
|
||||||
_.each(children, function(child) {
|
_.each(children, function(child) {
|
||||||
var flex = child.get('visNode').get('maxWidth');
|
var flex = child.get('visNode').getMaxWidthScaled();
|
||||||
var portion = (flex / totalFlex) * myLength;
|
var portion = (flex / totalFlex) * myLength;
|
||||||
var childMin = prevBound;
|
var childMin = prevBound;
|
||||||
var childMax = childMin + portion;
|
var childMax = childMin + portion;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue