diff --git a/src/constants.js b/src/constants.js index aa96bed6..1f258526 100644 --- a/src/constants.js +++ b/src/constants.js @@ -22,6 +22,8 @@ var GRAPHICS = { rectStroke: '#FFF', rectStrokeWidth: '3', multiBranchY: 20, + upstreamHeadOpacity: 0.5, + upstreamNoneOpacity: 0.2, }; /** diff --git a/src/git.js b/src/git.js index a6e513fc..eacffe6a 100644 --- a/src/git.js +++ b/src/git.js @@ -308,7 +308,40 @@ GitEngine.prototype.getCommitFromRef = function(ref) { GitEngine.prototype.setLocationTarget = function(ref, target) { var ref = this.getOneBeforeCommit(ref); ref.set('target', target); -} +}; + +GitEngine.prototype.getUpstreamBranchSet = function() { + // this is expensive!! so only call once in a while + var commitToSet = {}; + + var bfsSearch = function(commit) { + var set = []; + var pQueue = [commit]; + while (pQueue.length) { + var popped = pQueue.pop(); + set.push(popped.get('id')); + + if (popped.get('parents') && popped.get('parents').length) { + pQueue = pQueue.concat(popped.get('parents')); + } + } + return set; + }; + + this.branches.each(function(branch) { + var set = bfsSearch(branch.get('target')); + _.each(set, function(id) { + commitToSet[id] = commitToSet[id] || []; + commitToSet[id].push(branch.get('id')); + }); + }); + + return commitToSet; +}; + +GitEngine.prototype.getUpstreamHeadSet = function() { + return this.getUpstreamSet('HEAD'); +}; GitEngine.prototype.getOneBeforeCommit = function(ref) { // you can call this command on HEAD in detached, HEAD, or on a branch @@ -726,11 +759,6 @@ GitEngine.prototype.dispatch = function(command, callback) { } })); - // TODO (get rid of) - for (var i = 0; i < 1; i++) { - this.animationQueue.add(new Animation({closure: function() { console.log(Math.random()); }})); - } - // animation queue will call the callback when its done this.animationQueue.start(); }; diff --git a/src/tree.js b/src/tree.js index bce2f31d..d8a8429c 100644 --- a/src/tree.js +++ b/src/tree.js @@ -299,11 +299,45 @@ var VisNode = Backbone.Model.extend({ this.get('circle').toFront(); }, + getOpacity: function() { + var map = { + 'branch': 1, + 'head': GRAPHICS.upstreamHeadOpacity, + 'none': GRAPHICS.upstreamNoneOpacity + }; + var stat = this.getUpstreamStatus(); + if (map[stat] === undefined) { + throw new Error('invalid status'); + } + return map[stat]; + }, + + getUpstreamStatus: function() { + if (!gitVisuals.upstreamBranchSet) { + throw new Error("Can't call this method yet"); + } + + var id = this.get('id'); + var branch = gitVisuals.upstreamBranchSet; + var head = gitVisuals.upstreamHeadSet; + + if (branch[id] && branch[id].length) { + return 'branch'; + } else if (head[id] && head[id].length) { + return 'head'; + } else { + return 'none' + } + }, + animateUpdatedPosition: function(speed, easing) { var pos = this.getScreenCoords(); + var opacity = this.getOpacity(); + this.get('circle').stop().animate({ cx: pos.x, - cy: pos.y + cy: pos.y, + opacity: opacity }, speed !== undefined ? speed : this.get('animationSpeed'), easing || this.get('animationEasing') diff --git a/src/visuals.js b/src/visuals.js index d54a7f87..93dfee82 100644 --- a/src/visuals.js +++ b/src/visuals.js @@ -8,7 +8,9 @@ function GitVisuals(options) { this.commitMap = {}; this.rootCommit = null; - this.branchStackMap = {}; + this.branchStackMap = null; + this.upstreamBranchSet = null; + this.upstreamHeadSet = null; this.paperReady = false; this.paperWidth = null; @@ -73,14 +75,14 @@ GitVisuals.prototype.toScreenCoords = function(pos) { GitVisuals.prototype.refreshTree = function() { // this method can only be called after graphics are rendered - this.calculateTreeCoords(); - this.calculateGraphicsCoords(); + this.calcTreeCoords(); + this.calcGraphicsCoords(); this.animateAll(); }; GitVisuals.prototype.refreshTreeHarsh = function() { - this.calculateTreeCoords(); + this.calcTreeCoords(); this.animateAll(0); }; @@ -93,7 +95,7 @@ GitVisuals.prototype.animateAll = function(speed) { this.animateRefs(speed); }; -GitVisuals.prototype.calculateTreeCoords = function() { +GitVisuals.prototype.calcTreeCoords = function() { // this method can only contain things that dont rely on graphics if (!this.rootCommit) { throw new Error('grr, no root commit!'); @@ -103,14 +105,20 @@ GitVisuals.prototype.calculateTreeCoords = function() { this.calcWidth(); this.calcBranchStacks(); + this.calcUpstreamSets(); }; -GitVisuals.prototype.calculateGraphicsCoords = function() { +GitVisuals.prototype.calcGraphicsCoords = function() { this.visBranchCollection.each(function(visBranch) { visBranch.updateName(); }); }; +GitVisuals.prototype.calcUpstreamSets = function() { + this.upstreamBranchSet = gitEngine.getUpstreamBranchSet(); + this.upstreamHeadSet = gitEngine.getUpstreamHeadSet(); +}; + GitVisuals.prototype.calcBranchStacks = function() { var branches = gitEngine.getBranches(); var map = {}; @@ -172,7 +180,7 @@ GitVisuals.prototype.assignBoundsRecursive = function(commit, min, max) { var prevBound = min; // 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) { var flex = child.get('visNode').get('maxWidth'); var portion = (flex / totalFlex) * myLength; @@ -339,7 +347,7 @@ GitVisuals.prototype.zIndexReflow = function() { GitVisuals.prototype.drawTreeFirstTime = function() { this.paperReady = true; - this.calculateTreeCoords(); + this.calcTreeCoords(); _.each(this.visNodeMap, function(visNode) { visNode.genGraphics(paper);