Merge branch 'tagSupport' Pull Request #137 Issue #134

Conflicts:
	src/js/git/index.js
This commit is contained in:
Peter Cottle 2013-10-27 12:37:48 -07:00
commit ebfd5e84d2
10 changed files with 647 additions and 6 deletions

View file

@ -731,6 +731,24 @@ var commandConfig = {
source: source source: source
}); });
} }
},
tag: {
regex: /^git +tag($|\s)/,
execute: function(engine, command) {
var generalArgs = command.getGeneralArgs();
if (generalArgs.length === 0) {
var tags = engine.getTags();
engine.printTags(tags);
return;
}
command.twoArgsImpliedHead(generalArgs);
engine.tag(generalArgs[0], generalArgs[1]);
}
} }
}; };

View file

@ -41,6 +41,7 @@ function GitEngine(options) {
this.localRepo = null; this.localRepo = null;
this.branchCollection = options.branches; this.branchCollection = options.branches;
this.tagCollection = options.tags;
this.commitCollection = options.collection; this.commitCollection = options.collection;
this.gitVisuals = options.gitVisuals; this.gitVisuals = options.gitVisuals;
@ -214,6 +215,7 @@ GitEngine.prototype.exportTree = function() {
_.each(this.branchCollection.toJSON(), function(branch) { _.each(this.branchCollection.toJSON(), function(branch) {
branch.target = branch.target.get('id'); branch.target = branch.target.get('id');
branch.visBranch = undefined; branch.visBranch = undefined;
branch.visTag = undefined;
totalExport.branches[branch.id] = branch; totalExport.branches[branch.id] = branch;
}); });
@ -235,8 +237,7 @@ GitEngine.prototype.exportTree = function() {
}, this); }, this);
var HEAD = this.HEAD.toJSON(); var HEAD = this.HEAD.toJSON();
HEAD.visBranch = undefined; HEAD.lastTarget = HEAD.lastLastTarget = HEAD.visBranch = HEAD.visTag =undefined;
HEAD.lastTarget = HEAD.lastLastTarget = HEAD.visBranch = undefined;
HEAD.target = HEAD.target.get('id'); HEAD.target = HEAD.target.get('id');
totalExport.HEAD = HEAD; totalExport.HEAD = HEAD;
@ -298,6 +299,12 @@ GitEngine.prototype.instantiateFromTree = function(tree) {
this.branchCollection.add(branch, {silent: true}); this.branchCollection.add(branch, {silent: true});
}, this); }, this);
_.each(tree.tags, function(tagJSON) {
var tag = this.getOrMakeRecursive(tree, createdSoFar, tagJSON.id);
this.tagCollection.add(tag, {silent: true});
}, this);
var HEAD = this.getOrMakeRecursive(tree, createdSoFar, tree.HEAD.id); var HEAD = this.getOrMakeRecursive(tree, createdSoFar, tree.HEAD.id);
this.HEAD = HEAD; this.HEAD = HEAD;
@ -311,6 +318,9 @@ GitEngine.prototype.instantiateFromTree = function(tree) {
this.branchCollection.each(function(branch) { this.branchCollection.each(function(branch) {
this.gitVisuals.addBranch(branch); this.gitVisuals.addBranch(branch);
}, this); }, this);
this.tagCollection.each(function(tag) {
this.gitVisuals.addTag(tag);
}, this);
if (tree.originTree) { if (tree.originTree) {
var treeString = JSON.stringify(tree.originTree); var treeString = JSON.stringify(tree.originTree);
@ -512,6 +522,19 @@ GitEngine.prototype.getOrMakeRecursive = function(tree, createdSoFar, objID) {
return branch; return branch;
} }
if (type == 'tag') {
var tagJSON = tree.tags[objID];
var tag = new Tag(_.extend(
tree.tags[objID],
{
target: this.getOrMakeRecursive(tree, createdSoFar, tagJSON.target)
}
));
createdSoFar[objID] = tag;
return tag;
}
if (type == 'commit') { if (type == 'commit') {
// for commits, we need to grab all the parents // for commits, we need to grab all the parents
var commitJSON = tree.commits[objID]; var commitJSON = tree.commits[objID];
@ -559,6 +582,7 @@ GitEngine.prototype.reloadGraphics = function() {
GitEngine.prototype.removeAll = function() { GitEngine.prototype.removeAll = function() {
this.branchCollection.reset(); this.branchCollection.reset();
this.tagCollection.reset();
this.commitCollection.reset(); this.commitCollection.reset();
this.refs = {}; this.refs = {};
this.HEAD = null; this.HEAD = null;
@ -625,6 +649,20 @@ GitEngine.prototype.validateAndMakeBranch = function(id, target) {
return this.makeBranch(id, target); return this.makeBranch(id, target);
}; };
GitEngine.prototype.validateAndMakeTag = function(id, target) {
id = this.validateBranchName(id);
if (this.refs[id]) {
throw new GitError({
msg: intl.str(
'bad-tag-name',
{ tag: name }
)
});
}
this.makeTag(id, target);
};
GitEngine.prototype.makeBranch = function(id, target) { GitEngine.prototype.makeBranch = function(id, target) {
if (this.refs[id]) { if (this.refs[id]) {
throw new Error('woah already have that'); throw new Error('woah already have that');
@ -639,10 +677,37 @@ GitEngine.prototype.makeBranch = function(id, target) {
return branch; return branch;
}; };
GitEngine.prototype.makeTag = function(id, target) {
if (this.refs[id]) {
throw new Error('woah already have that');
}
var tag = new Tag({
target: target,
id: id
});
this.tagCollection.add(tag);
this.refs[tag.get('id')] = tag;
return tag;
};
GitEngine.prototype.getHead = function() { GitEngine.prototype.getHead = function() {
return _.clone(this.HEAD); return _.clone(this.HEAD);
}; };
GitEngine.prototype.getTags = function() {
var toReturn = [];
this.tagCollection.each(function(tag) {
toReturn.push({
id: tag.get('id'),
target: tag.get('target'),
remote: tag.getIsRemote(),
obj: tag
});
}, this);
return toReturn;
};
GitEngine.prototype.getBranches = function() { GitEngine.prototype.getBranches = function() {
var toReturn = []; var toReturn = [];
this.branchCollection.each(function(branch) { this.branchCollection.each(function(branch) {
@ -693,6 +758,17 @@ GitEngine.prototype.printBranches = function(branches) {
}); });
}; };
GitEngine.prototype.printTags = function(tags) {
var result = '';
_.each(tags, function(tag) {
console.log(tag);
result += tag.id + '\n';
});
throw new CommandResult({
msg: result
});
};
GitEngine.prototype.printRemotes = function(options) { GitEngine.prototype.printRemotes = function(options) {
var result = ''; var result = '';
if (options.verbose) { if (options.verbose) {
@ -2261,11 +2337,14 @@ GitEngine.prototype.checkout = function(idOrTarget) {
target = this.getCommitFromRef(target.get('id')); target = this.getCommitFromRef(target.get('id'));
} }
if (type !== 'branch' && type !== 'commit') { if (type !== 'branch' && type !== 'tag' && type !== 'commit') {
throw new GitError({ throw new GitError({
msg: intl.str('git-error-options') msg: intl.str('git-error-options')
}); });
} }
if (type === 'tag') {
target = target.get('target');
}
this.HEAD.set('target', target); this.HEAD.set('target', target);
}; };
@ -2313,6 +2392,11 @@ GitEngine.prototype.isRemoteBranchRef = function(ref) {
return resolved.getIsRemote(); return resolved.getIsRemote();
}; };
GitEngine.prototype.tag = function(name, ref) {
var target = this.getCommitFromRef(ref);
this.validateAndMakeTag(name, target);
};
GitEngine.prototype.validateAndDeleteBranch = function(name) { GitEngine.prototype.validateAndDeleteBranch = function(name) {
// trying to delete, lets check our refs // trying to delete, lets check our refs
var target = this.resolveID(name); var target = this.resolveID(name);
@ -2810,8 +2894,20 @@ var Commit = Backbone.Model.extend({
} }
}); });
var Tag = Ref.extend({
defaults: {
visTag: null
},
initialize: function() {
Ref.prototype.initialize.call(this);
this.set('type', 'tag');
}
});
exports.GitEngine = GitEngine; exports.GitEngine = GitEngine;
exports.Commit = Commit; exports.Commit = Commit;
exports.Branch = Branch; exports.Branch = Branch;
exports.Tag = Tag;
exports.Ref = Ref; exports.Ref = Ref;

View file

@ -288,6 +288,11 @@ exports.strings = {
'fr_FR': 'Ce nom de branche "{branch}" n\'est pas autorisé' 'fr_FR': 'Ce nom de branche "{branch}" n\'est pas autorisé'
}, },
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
'bad-tag-name': {
'__desc__': 'When the user enters a tag name thats not ok',
'en_US': 'That tag name "{tag}" is not allowed!'
},
///////////////////////////////////////////////////////////////////////////
'option-not-supported': { 'option-not-supported': {
'__desc__': 'When the user specifies an option that is not supported by our demo', '__desc__': 'When the user specifies an option that is not supported by our demo',
'en_US': 'The option "{option}" is not supported!', 'en_US': 'The option "{option}" is not supported!',

View file

@ -5,6 +5,7 @@ var Backbone = (!require('../util').isBrowser()) ? Backbone = require('backbone'
var Commit = require('../git').Commit; var Commit = require('../git').Commit;
var Branch = require('../git').Branch; var Branch = require('../git').Branch;
var Tag = require('../git').Tag;
var Command = require('../models/commandModel').Command; var Command = require('../models/commandModel').Command;
var CommandEntry = require('../models/commandModel').CommandEntry; var CommandEntry = require('../models/commandModel').CommandEntry;
@ -22,6 +23,10 @@ var BranchCollection = Backbone.Collection.extend({
model: Branch model: Branch
}); });
var TagCollection = Backbone.Collection.extend({
model: Tag
});
var CommandEntryCollection = Backbone.Collection.extend({ var CommandEntryCollection = Backbone.Collection.extend({
model: CommandEntry, model: CommandEntry,
localStorage: (Backbone.LocalStorage) ? new Backbone.LocalStorage('CommandEntries') : null localStorage: (Backbone.LocalStorage) ? new Backbone.LocalStorage('CommandEntries') : null
@ -125,6 +130,7 @@ var CommandBuffer = Backbone.Model.extend({
exports.CommitCollection = CommitCollection; exports.CommitCollection = CommitCollection;
exports.CommandCollection = CommandCollection; exports.CommandCollection = CommandCollection;
exports.BranchCollection = BranchCollection; exports.BranchCollection = BranchCollection;
exports.TagCollection = TagCollection;
exports.CommandEntryCollection = CommandEntryCollection; exports.CommandEntryCollection = CommandEntryCollection;
exports.CommandBuffer = CommandBuffer; exports.CommandBuffer = CommandBuffer;

View file

@ -33,6 +33,7 @@ var GRAPHICS = {
originDash: '- ', originDash: '- ',
multiBranchY: 20, multiBranchY: 20,
multiTagY: 15,
upstreamHeadOpacity: 0.5, upstreamHeadOpacity: 0.5,
upstreamNoneOpacity: 0.2, upstreamNoneOpacity: 0.2,
edgeUpstreamHeadOpacity: 0.4, edgeUpstreamHeadOpacity: 0.4,
@ -45,6 +46,10 @@ var GRAPHICS = {
defaultNodeStrokeWidth: 2, defaultNodeStrokeWidth: 2,
defaultNodeStroke: '#FFF', defaultNodeStroke: '#FFF',
tagFill: 'hsb(0,0,0.9)',
tagStroke: '#FFF',
tagStrokeWidth: '2',
orphanNodeFill: 'hsb(0.5,0.8,0.7)' orphanNodeFill: 'hsb(0.5,0.8,0.7)'
}; };

View file

@ -8,10 +8,13 @@ var GLOBAL = require('../util/constants').GLOBAL;
var Collections = require('../models/collections'); var Collections = require('../models/collections');
var CommitCollection = Collections.CommitCollection; var CommitCollection = Collections.CommitCollection;
var BranchCollection = Collections.BranchCollection; var BranchCollection = Collections.BranchCollection;
var TagCollection = Collections.TagCollection;
var VisNode = require('../visuals/visNode').VisNode; var VisNode = require('../visuals/visNode').VisNode;
var VisBranch = require('../visuals/visBranch').VisBranch; var VisBranch = require('../visuals/visBranch').VisBranch;
var VisBranchCollection = require('../visuals/visBranch').VisBranchCollection; var VisBranchCollection = require('../visuals/visBranch').VisBranchCollection;
var VisTag = require('../visuals/visTag').VisTag;
var VisTagCollection = require('../visuals/visTag').VisTagCollection;
var VisEdge = require('../visuals/visEdge').VisEdge; var VisEdge = require('../visuals/visEdge').VisEdge;
var VisEdgeCollection = require('../visuals/visEdge').VisEdgeCollection; var VisEdgeCollection = require('../visuals/visEdge').VisEdgeCollection;
@ -21,14 +24,17 @@ function GitVisuals(options) {
this.visualization = options.visualization; this.visualization = options.visualization;
this.commitCollection = options.commitCollection; this.commitCollection = options.commitCollection;
this.branchCollection = options.branchCollection; this.branchCollection = options.branchCollection;
this.tagCollection = options.tagCollection;
this.visNodeMap = {}; this.visNodeMap = {};
this.visEdgeCollection = new VisEdgeCollection(); this.visEdgeCollection = new VisEdgeCollection();
this.visBranchCollection = new VisBranchCollection(); this.visBranchCollection = new VisBranchCollection();
this.visTagCollection = new VisTagCollection();
this.commitMap = {}; this.commitMap = {};
this.rootCommit = null; this.rootCommit = null;
this.branchStackMap = null; this.branchStackMap = null;
this.tagStackMap = null;
this.upstreamBranchSet = null; this.upstreamBranchSet = null;
this.upstreamHeadSet = null; this.upstreamHeadSet = null;
@ -37,6 +43,10 @@ function GitVisuals(options) {
this.branchCollection.on('add', this.addBranchFromEvent, this); this.branchCollection.on('add', this.addBranchFromEvent, this);
this.branchCollection.on('remove', this.removeBranch, this); this.branchCollection.on('remove', this.removeBranch, this);
this.tagCollection.on('add', this.addTagFromEvent, this);
this.tagCollection.on('remove', this.removeTag, this);
this.deferred = []; this.deferred = [];
this.flipFraction = 0.65; this.flipFraction = 0.65;
@ -69,12 +79,18 @@ GitVisuals.prototype.resetAll = function() {
visBranch.remove(); visBranch.remove();
}, this); }, this);
var tags = this.visTagCollection.toArray();
_.each(tags, function(visTag) {
visTag.remove();
}, this);
_.each(this.visNodeMap, function(visNode) { _.each(this.visNodeMap, function(visNode) {
visNode.remove(); visNode.remove();
}, this); }, this);
this.visEdgeCollection.reset(); this.visEdgeCollection.reset();
this.visBranchCollection.reset(); this.visBranchCollection.reset();
this.visTagCollection.reset();
this.visNodeMap = {}; this.visNodeMap = {};
this.rootCommit = null; this.rootCommit = null;
@ -178,6 +194,7 @@ GitVisuals.prototype.animateAllAttrKeys = function(keys, attr, speed, easing) {
this.visBranchCollection.each(animate); this.visBranchCollection.each(animate);
this.visEdgeCollection.each(animate); this.visEdgeCollection.each(animate);
this.visTagCollection.each(animate);
_.each(this.visNodeMap, animate); _.each(this.visNodeMap, animate);
var time = (speed !== undefined) ? speed : GRAPHICS.defaultAnimationTime; var time = (speed !== undefined) ? speed : GRAPHICS.defaultAnimationTime;
@ -334,6 +351,7 @@ GitVisuals.prototype.animateAllFromAttrToAttr = function(fromSnapshot, toSnapsho
this.visBranchCollection.each(animate); this.visBranchCollection.each(animate);
this.visEdgeCollection.each(animate); this.visEdgeCollection.each(animate);
this.visTagCollection.each(animate);
_.each(this.visNodeMap, animate); _.each(this.visNodeMap, animate);
}; };
@ -370,6 +388,10 @@ GitVisuals.prototype.genSnapshot = function() {
snapshot[visEdge.getID()] = visEdge.getAttributes(); snapshot[visEdge.getID()] = visEdge.getAttributes();
}, this); }, this);
this.visTagCollection.each(function(visTag) {
snapshot[visTag.getID()] = visTag.getAttributes();
}, this);
return snapshot; return snapshot;
}; };
@ -411,6 +433,7 @@ GitVisuals.prototype.calcTreeCoords = function() {
this.calcUpstreamSets(); this.calcUpstreamSets();
this.calcBranchStacks(); this.calcBranchStacks();
this.calcTagStacks();
this.calcDepth(); this.calcDepth();
this.calcWidth(); this.calcWidth();
@ -420,6 +443,9 @@ GitVisuals.prototype.calcGraphicsCoords = function() {
this.visBranchCollection.each(function(visBranch) { this.visBranchCollection.each(function(visBranch) {
visBranch.updateName(); visBranch.updateName();
}); });
this.visTagCollection.each(function(visTag) {
visTag.updateName();
});
}; };
GitVisuals.prototype.calcUpstreamSets = function() { GitVisuals.prototype.calcUpstreamSets = function() {
@ -496,6 +522,23 @@ GitVisuals.prototype.calcBranchStacks = function() {
this.branchStackMap = map; this.branchStackMap = map;
}; };
GitVisuals.prototype.calcTagStacks = function() {
var tags = this.gitEngine.getTags();
var map = {};
_.each(tags, function(tag) {
var thisId = tag.target.get('id');
map[thisId] = map[thisId] || [];
map[thisId].push(tag);
map[thisId].sort(function(a, b) {
var aId = a.obj.get('id');
var bId = b.obj.get('id');
return aId.localeCompare(bId);
});
});
this.tagStackMap = map;
};
GitVisuals.prototype.calcWidth = function() { GitVisuals.prototype.calcWidth = function() {
this.maxWidthRecursive(this.rootCommit); this.maxWidthRecursive(this.rootCommit);
@ -626,10 +669,44 @@ GitVisuals.prototype.addBranch = function(branch) {
} }
}; };
GitVisuals.prototype.addTagFromEvent = function(tag, collection, index) {
var action = _.bind(function() {
this.addTag(tag);
}, this);
if (!this.gitEngine || !this.gitReady) {
this.defer(action);
} else {
action();
}
};
GitVisuals.prototype.addTag = function(tag) {
var visTag = new VisTag({
tag: tag,
gitVisuals: this,
gitEngine: this.gitEngine
});
this.visTagCollection.add(visTag);
if (this.gitReady) {
visTag.genGraphics(this.paper);
} else {
this.defer(_.bind(function() {
visTag.genGraphics(this.paper);
}, this));
}
};
GitVisuals.prototype.removeVisBranch = function(visBranch) { GitVisuals.prototype.removeVisBranch = function(visBranch) {
this.visBranchCollection.remove(visBranch); this.visBranchCollection.remove(visBranch);
}; };
GitVisuals.prototype.removeVisTag = function(visTag) {
this.visTagCollection.remove(visTag);
};
GitVisuals.prototype.removeVisNode = function(visNode) { GitVisuals.prototype.removeVisNode = function(visNode) {
delete this.visNodeMap[visNode.getID()]; delete this.visNodeMap[visNode.getID()];
}; };
@ -642,6 +719,9 @@ GitVisuals.prototype.animateRefs = function(speed) {
this.visBranchCollection.each(function(visBranch) { this.visBranchCollection.each(function(visBranch) {
visBranch.animateUpdatedPos(speed); visBranch.animateUpdatedPos(speed);
}, this); }, this);
this.visTagCollection.each(function(visTag) {
visTag.animateUpdatedPos(speed);
}, this);
}; };
GitVisuals.prototype.animateEdges = function(speed) { GitVisuals.prototype.animateEdges = function(speed) {
@ -756,6 +836,7 @@ GitVisuals.prototype.addEdge = function(idTail, idHead) {
GitVisuals.prototype.zIndexReflow = function() { GitVisuals.prototype.zIndexReflow = function() {
this.visNodesFront(); this.visNodesFront();
this.visBranchesFront(); this.visBranchesFront();
this.visTagsFront();
}; };
GitVisuals.prototype.visNodesFront = function() { GitVisuals.prototype.visNodesFront = function() {
@ -775,6 +856,17 @@ GitVisuals.prototype.visBranchesFront = function() {
}); });
}; };
GitVisuals.prototype.visTagsFront = function() {
this.visTagCollection.each(function(vTag) {
vTag.nonTextToFront();
vTag.textToFront();
});
this.visTagCollection.each(function(vTag) {
vTag.textToFrontIfInStack();
});
};
GitVisuals.prototype.drawTreeFromReload = function() { GitVisuals.prototype.drawTreeFromReload = function() {
this.gitReady = true; this.gitReady = true;
// gen all the graphics we need // gen all the graphics we need
@ -799,6 +891,10 @@ GitVisuals.prototype.drawTreeFirstTime = function() {
visBranch.genGraphics(this.paper); visBranch.genGraphics(this.paper);
}, this); }, this);
this.visTagCollection.each(function(visTag) {
visTag.genGraphics(this.paper);
}, this);
this.zIndexReflow(); this.zIndexReflow();
}; };

View file

@ -130,6 +130,7 @@ var VisEdge = VisBase.extend({
var stat = this.gitVisuals.getCommitUpstreamStatus(this.get('tail')); var stat = this.gitVisuals.getCommitUpstreamStatus(this.get('tail'));
var map = { var map = {
'branch': 1, 'branch': 1,
'tag': 1,
'head': GRAPHICS.edgeUpstreamHeadOpacity, 'head': GRAPHICS.edgeUpstreamHeadOpacity,
'none': GRAPHICS.edgeUpstreamNoneOpacity 'none': GRAPHICS.edgeUpstreamNoneOpacity
}; };

View file

@ -74,6 +74,7 @@ var VisNode = VisBase.extend({
var stat = this.gitVisuals.getCommitUpstreamStatus(this.get('commit')); var stat = this.gitVisuals.getCommitUpstreamStatus(this.get('commit'));
var map = { var map = {
branch: 1, branch: 1,
tag: 1,
head: 0.3, head: 0.3,
none: 0.1 none: 0.1
}; };
@ -89,6 +90,7 @@ var VisNode = VisBase.extend({
getOpacity: function() { getOpacity: function() {
var map = { var map = {
'branch': 1, 'branch': 1,
'tag' : 1,
'head': GRAPHICS.upstreamHeadOpacity, 'head': GRAPHICS.upstreamHeadOpacity,
'none': GRAPHICS.upstreamNoneOpacity 'none': GRAPHICS.upstreamNoneOpacity
}; };

408
src/js/visuals/visTag.js Normal file
View file

@ -0,0 +1,408 @@
var _ = require('underscore');
var Backbone = require('backbone');
var GRAPHICS = require('../util/constants').GRAPHICS;
var VisBase = require('../visuals/visBase').VisBase;
var TreeCompare = require('../git/treeCompare').TreeCompare;
var randomHueString = function() {
var hue = Math.random();
var str = 'hsb(' + String(hue) + ',0.7,1)';
return str;
};
var VisTag = VisBase.extend({
defaults: {
pos: null,
text: null,
rect: null,
isHead: false,
fill: GRAPHICS.tagFill,
stroke: GRAPHICS.tagStroke,
'stroke-width': GRAPHICS.tagStrokeWidth,
offsetX: GRAPHICS.nodeRadius,
offsetY: GRAPHICS.nodeRadius,
vPad: 2,
hPad: 2,
animationSpeed: GRAPHICS.defaultAnimationTime,
animationEasing: GRAPHICS.defaultEasing
},
validateAtInit: function() {
if (!this.get('tag')) {
throw new Error('need a Tag!');
}
},
getID: function() {
return this.get('tag').get('id');
},
initialize: function() {
this.validateAtInit();
// shorthand notation for the main objects
this.gitVisuals = this.get('gitVisuals');
this.gitEngine = this.get('gitEngine');
if (!this.gitEngine) {
throw new Error('asd wtf');
}
this.get('tag').set('visTag', this);
},
getCommitPosition: function() {
var commit = this.gitEngine.getCommitFromRef(this.get('tag'));
var visNode = commit.get('visNode');
return visNode.getScreenCoords();
},
getDashArray: function() {
if (!this.get('gitVisuals').getIsGoalVis()) {
return '';
}
return (this.getIsLevelTagCompared()) ? '' : '--';
},
getIsGoalAndNotCompared: function() {
if (!this.get('gitVisuals').getIsGoalVis()) {
return false;
}
return !this.getIsLevelTagCompared();
},
/**
* returns true if we are a Tag that is not being
* compared in the goal (used in a goal visualization context
*/
getIsLevelTagCompared: function() {
// we are not master, so return true if its not just master being compared
var levelBlob = this.get('gitVisuals').getLevelBlob();
return !TreeCompare.onlyMasterCompared(levelBlob);
},
getTagStackIndex: function() {
if (this.get('isHead')) {
// head is never stacked with other Tages
return 0;
}
var myArray = this.getTagStackArray();
var index = -1;
_.each(myArray, function(Tag, i) {
if (Tag.obj == this.get('tag')) {
index = i;
}
}, this);
return index;
},
getTagStackLength: function() {
if (this.get('isHead')) {
// head is always by itself
return 1;
}
return this.getTagStackArray().length;
},
isTagStackEmpty: function() {
// useful function for head when computing flip logic
var arr = this.gitVisuals.tagStackMap[this.getCommitID()];
return (arr) ?
arr.length === 0 :
true;
},
getCommitID: function() {
var target = this.get('tag').get('target');
return target.get('id');
},
getTagStackArray: function() {
var arr = this.gitVisuals.tagStackMap[this.getCommitID()];
if (arr === undefined) {
// this only occurs when we are generating graphics inside of
// a new Tag instantiation, so we need to force the update
this.gitVisuals.calcTagStacks();
return this.getTagStackArray();
}
return arr;
},
getTextPosition: function() {
var pos = this.getCommitPosition();
// then order yourself accordingly. we use alphabetical sorting
// so everything is independent
var myPos = this.getTagStackIndex();
return {
x: pos.x + this.get('offsetX'),
y: pos.y + myPos * GRAPHICS.multiTagY + this.get('offsetY')
};
},
getRectPosition: function() {
var pos = this.getTextPosition();
// first get text width and height
var textSize = this.getTextSize();
return {
x: pos.x - this.get('hPad'),
y: pos.y - 0.5 * textSize.h - this.get('vPad')
};
},
getTextSize: function() {
var getTextWidth = function(visTag) {
var textNode = (visTag.get('text')) ? visTag.get('text').node : null;
return (textNode === null) ? 0 : textNode.clientWidth;
};
var firefoxFix = function(obj) {
if (!obj.w) { obj.w = 75; }
if (!obj.h) { obj.h = 20; }
return obj;
};
var textNode = this.get('text').node;
var maxWidth = 0;
_.each(this.getTagStackArray(), function(Tag) {
maxWidth = Math.max(maxWidth, getTextWidth(
Tag.obj.get('visTag')
));
});
return firefoxFix({
w: maxWidth,
h: textNode.clientHeight
});
},
getSingleRectSize: function() {
var textSize = this.getTextSize();
var vPad = this.get('vPad');
var hPad = this.get('hPad');
return {
w: textSize.w + vPad * 2,
h: textSize.h + hPad * 2
};
},
getRectSize: function() {
var textSize = this.getTextSize();
// enforce padding
var vPad = this.get('vPad');
var hPad = this.get('hPad');
// number of other Tag names we are housing
var totalNum = this.getTagStackLength();
return {
w: textSize.w + vPad * 2,
h: textSize.h * totalNum + hPad * 2
};
},
getIsRemote: function() {
return this.get('tag').getIsRemote();
},
getName: function() {
var name = this.get('tag').getName();
var isRemote = this.getIsRemote();
var isHg = this.gitEngine.getIsHg();
return name;
},
nonTextToFront: function() {
this.get('rect').toFront();
},
textToFront: function() {
this.get('text').toFront();
},
textToFrontIfInStack: function() {
if (this.getTagStackIndex() !== 0) {
this.get('text').toFront();
}
},
remove: function() {
this.removeKeys(['text', 'rect']);
// also need to remove from this.gitVisuals
this.gitVisuals.removeVisTag(this);
},
handleModeChange: function() {
},
genGraphics: function(paper) {
var textPos = this.getTextPosition();
var name = this.getName();
// when from a reload, we dont need to generate the text
var text = paper.text(textPos.x, textPos.y, String(name));
text.attr({
'font-size': 14,
'font-family': 'Monaco, Courier, font-monospace',
opacity: this.getTextOpacity(),
'text-anchor': 'start'
});
this.set('text', text);
var attr = this.getAttributes();
var rectPos = this.getRectPosition();
var sizeOfRect = this.getRectSize();
var rect = paper
.rect(rectPos.x, rectPos.y, sizeOfRect.w, sizeOfRect.h, 8)
.attr(attr.rect);
this.set('rect', rect);
// set CSS
var keys = ['text', 'rect'];
_.each(keys, function(key) {
$(this.get(key).node).css(attr.css);
}, this);
this.attachClickHandlers();
rect.toFront();
text.toFront();
},
attachClickHandlers: function() {
if (this.get('gitVisuals').options.noClick) {
return;
}
var objs = [
this.get('rect'),
this.get('text')
];
_.each(objs, function(rObj) {
rObj.click(_.bind(this.onClick ,this));
}, this);
},
shouldDisableClick: function() {
return this.get('isHead') && !this.gitEngine.getDetachedHead();
},
onClick: function() {
if (this.shouldDisableClick()) {
return;
}
var commandStr = 'git checkout ' + this.get('tag').get('id');
var Main = require('../app');
Main.getEventBaton().trigger('commandSubmitted', commandStr);
},
updateName: function() {
this.get('text').attr({
text: this.getName()
});
},
getNonTextOpacity: function() {
if (this.get('isHead')) {
return this.gitEngine.getDetachedHead() ? 1 : 0;
}
if (this.getTagStackIndex() !== 0) {
return 0.0;
}
return 1;
},
getTextOpacity: function() {
if (this.get('isHead')) {
return this.gitEngine.getDetachedHead() ? 1 : 0;
}
if (this.getIsGoalAndNotCompared()) {
return (this.getTagStackIndex() === 0) ? 0.7 : 0.3;
}
return 1;
},
getStrokeWidth: function() {
if (this.getIsGoalAndNotCompared()) {
return this.get('stroke-width') / 5.0;
}
return this.get('stroke-width');
},
getAttributes: function() {
var textOpacity = this.getTextOpacity();
this.updateName();
var textPos = this.getTextPosition();
var rectPos = this.getRectPosition();
var rectSize = this.getRectSize();
var dashArray = this.getDashArray();
var cursorStyle = (this.shouldDisableClick()) ?
'auto' :
'pointer';
return {
css: {
cursor: cursorStyle
},
text: {
x: textPos.x,
y: textPos.y,
opacity: textOpacity
},
rect: {
x: rectPos.x,
y: rectPos.y,
width: rectSize.w,
height: rectSize.h,
opacity: this.getNonTextOpacity(),
fill: this.get('fill'),
stroke: this.get('stroke'),
'stroke-dasharray': dashArray,
'stroke-width': this.getStrokeWidth()
}
};
},
animateUpdatedPos: 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);
},
setAttr: function(attr, instant, speed, easing) {
var keys = ['text', 'rect'];
this.setAttrBase(keys, attr, instant, speed, easing);
}
});
var VisTagCollection = Backbone.Collection.extend({
model: VisTag
});
exports.VisTagCollection = VisTagCollection;
exports.VisTag = VisTag;
exports.randomHueString = randomHueString;

View file

@ -5,6 +5,7 @@ var Backbone = (!require('../util').isBrowser()) ? Backbone = require('backbone'
var Collections = require('../models/collections'); var Collections = require('../models/collections');
var CommitCollection = Collections.CommitCollection; var CommitCollection = Collections.CommitCollection;
var BranchCollection = Collections.BranchCollection; var BranchCollection = Collections.BranchCollection;
var TagCollection = Collections.TagCollection;
var EventBaton = require('../util/eventBaton').EventBaton; var EventBaton = require('../util/eventBaton').EventBaton;
var GitVisuals = require('../visuals').GitVisuals; var GitVisuals = require('../visuals').GitVisuals;
@ -43,10 +44,12 @@ var Visualization = Backbone.View.extend({
this.commitCollection = new CommitCollection(); this.commitCollection = new CommitCollection();
this.branchCollection = new BranchCollection(); this.branchCollection = new BranchCollection();
this.tagCollection = new TagCollection();
this.gitVisuals = new GitVisuals({ this.gitVisuals = new GitVisuals({
commitCollection: this.commitCollection, commitCollection: this.commitCollection,
branchCollection: this.branchCollection, branchCollection: this.branchCollection,
tagCollection: this.tagCollection,
paper: this.paper, paper: this.paper,
noClick: this.options.noClick, noClick: this.options.noClick,
isGoalVis: this.options.isGoalVis, isGoalVis: this.options.isGoalVis,
@ -58,6 +61,7 @@ var Visualization = Backbone.View.extend({
this.gitEngine = new GitEngine({ this.gitEngine = new GitEngine({
collection: this.commitCollection, collection: this.commitCollection,
branches: this.branchCollection, branches: this.branchCollection,
tags: this.tagCollection,
gitVisuals: this.gitVisuals, gitVisuals: this.gitVisuals,
eventBaton: this.eventBaton eventBaton: this.eventBaton
}); });