mirror of
https://github.com/pcottle/learnGitBranching.git
synced 2025-07-02 18:54:27 +02:00
187 lines
5 KiB
JavaScript
187 lines
5 KiB
JavaScript
var _ = require('underscore');
|
|
var Backbone = require('backbone');
|
|
var GRAPHICS = require('../util/constants').GRAPHICS;
|
|
|
|
var VisBase = require('../visuals/visBase').VisBase;
|
|
var GlobalState = require('../util/globalState');
|
|
|
|
var VisEdge = VisBase.extend({
|
|
defaults: {
|
|
tail: null,
|
|
head: null,
|
|
animationSpeed: GRAPHICS.defaultAnimationTime,
|
|
animationEasing: GRAPHICS.defaultEasing
|
|
},
|
|
|
|
validateAtInit: function() {
|
|
var required = ['tail', 'head'];
|
|
_.each(required, function(key) {
|
|
if (!this.get(key)) {
|
|
throw new Error(key + ' is required!');
|
|
}
|
|
}, this);
|
|
},
|
|
|
|
getID: function() {
|
|
return this.get('tail').get('id') + '.' + this.get('head').get('id');
|
|
},
|
|
|
|
initialize: function() {
|
|
this.validateAtInit();
|
|
|
|
// shorthand for the main objects
|
|
this.gitVisuals = this.get('gitVisuals');
|
|
this.gitEngine = this.get('gitEngine');
|
|
|
|
this.get('tail').get('outgoingEdges').push(this);
|
|
},
|
|
|
|
remove: function() {
|
|
this.removeKeys(['path']);
|
|
this.gitVisuals.removeVisEdge(this);
|
|
},
|
|
|
|
genSmoothBezierPathString: function(tail, head) {
|
|
var tailPos = tail.getScreenCoords();
|
|
var headPos = head.getScreenCoords();
|
|
return this.genSmoothBezierPathStringFromCoords(tailPos, headPos);
|
|
},
|
|
|
|
genSmoothBezierPathStringFromCoords: function(tailPos, headPos) {
|
|
// we need to generate the path and control points for the bezier. format
|
|
// is M(move abs) C (curve to) (control point 1) (control point 2) (final point)
|
|
// the control points have to be __below__ to get the curve starting off straight.
|
|
|
|
var flipFactor = (GlobalState.flipTreeY) ? -1 : 1;
|
|
var coords = function(pos) {
|
|
return String(Math.round(pos.x)) + ',' + String(Math.round(pos.y));
|
|
};
|
|
var offset = function(pos, dir, delta) {
|
|
delta = delta || GRAPHICS.curveControlPointOffset;
|
|
return {
|
|
x: pos.x,
|
|
y: pos.y + flipFactor * delta * dir
|
|
};
|
|
};
|
|
var offset2d = function(pos, x, y) {
|
|
return {
|
|
x: pos.x + x,
|
|
y: pos.y + flipFactor * y
|
|
};
|
|
};
|
|
|
|
// first offset tail and head by radii
|
|
tailPos = offset(tailPos, -1, this.get('tail').getRadius());
|
|
headPos = offset(headPos, 1, this.get('head').getRadius() * 1.15);
|
|
|
|
var str = '';
|
|
// first move to bottom of tail
|
|
str += 'M' + coords(tailPos) + ' ';
|
|
// start bezier
|
|
str += 'C';
|
|
// then control points above tail and below head
|
|
str += coords(offset(tailPos, -1)) + ' ';
|
|
str += coords(offset(headPos, 1)) + ' ';
|
|
// now finish
|
|
str += coords(headPos);
|
|
|
|
// arrow head
|
|
var delta = GRAPHICS.arrowHeadSize || 10;
|
|
str += ' L' + coords(offset2d(headPos, -delta, delta));
|
|
str += ' L' + coords(offset2d(headPos, delta, delta));
|
|
str += ' L' + coords(headPos);
|
|
|
|
// then go back, so we can fill correctly
|
|
str += 'C';
|
|
str += coords(offset(headPos, 1)) + ' ';
|
|
str += coords(offset(tailPos, -1)) + ' ';
|
|
str += coords(tailPos);
|
|
|
|
return str;
|
|
},
|
|
|
|
getBezierCurve: function() {
|
|
return this.genSmoothBezierPathString(this.get('tail'), this.get('head'));
|
|
},
|
|
|
|
getStrokeColor: function() {
|
|
return GRAPHICS.visBranchStrokeColorNone;
|
|
},
|
|
|
|
setOpacity: function(opacity) {
|
|
opacity = (opacity === undefined) ? 1 : opacity;
|
|
|
|
this.get('path').attr({opacity: opacity});
|
|
},
|
|
|
|
genGraphics: function(paper) {
|
|
var pathString = this.getBezierCurve();
|
|
|
|
var path = paper.path(pathString).attr({
|
|
'stroke-width': GRAPHICS.visBranchStrokeWidth,
|
|
'stroke': this.getStrokeColor(),
|
|
'stroke-linecap': 'round',
|
|
'stroke-linejoin': 'round',
|
|
'fill': this.getStrokeColor()
|
|
});
|
|
path.toBack();
|
|
this.set('path', path);
|
|
},
|
|
|
|
getOpacity: function() {
|
|
var stat = this.gitVisuals.getCommitUpstreamStatus(this.get('tail'));
|
|
var map = {
|
|
'branch': 1,
|
|
'tag': 1,
|
|
'head': GRAPHICS.edgeUpstreamHeadOpacity,
|
|
'none': GRAPHICS.edgeUpstreamNoneOpacity
|
|
};
|
|
|
|
if (map[stat] === undefined) { throw new Error('bad stat'); }
|
|
return map[stat];
|
|
},
|
|
|
|
getAttributes: function() {
|
|
var newPath = this.getBezierCurve();
|
|
var opacity = this.getOpacity();
|
|
return {
|
|
path: {
|
|
path: newPath,
|
|
opacity: opacity
|
|
}
|
|
};
|
|
},
|
|
|
|
animateUpdatedPath: function(speed, easing) {
|
|
var attr = this.getAttributes();
|
|
this.animateToAttr(attr, speed, easing);
|
|
},
|
|
|
|
animateFromAttrToAttr: function(fromAttr, toAttr, speed, easing) {
|
|
// an animation of 0 is essentially setting the attribute directly
|
|
this.animateToAttr(fromAttr, 0);
|
|
this.animateToAttr(toAttr, speed, easing);
|
|
},
|
|
|
|
animateToAttr: function(attr, speed, easing) {
|
|
if (speed === 0) {
|
|
this.get('path').attr(attr.path);
|
|
return;
|
|
}
|
|
|
|
this.get('path').toBack();
|
|
this.get('path').stop();
|
|
this.get('path').animate(
|
|
attr.path,
|
|
speed !== undefined ? speed : this.get('animationSpeed'),
|
|
easing || this.get('animationEasing')
|
|
);
|
|
}
|
|
});
|
|
|
|
var VisEdgeCollection = Backbone.Collection.extend({
|
|
model: VisEdge
|
|
});
|
|
|
|
exports.VisEdgeCollection = VisEdgeCollection;
|
|
exports.VisEdge = VisEdge;
|