mirror of
https://github.com/pcottle/learnGitBranching.git
synced 2025-06-27 08:28:50 +02:00
Support dragging the goal window
This commit is contained in:
parent
549e67b1c7
commit
f29252e6ad
5 changed files with 182 additions and 36 deletions
|
@ -50,6 +50,9 @@ var Level = Sandbox.extend({
|
||||||
|
|
||||||
this.initGoalData(options);
|
this.initGoalData(options);
|
||||||
this.initName(options);
|
this.initName(options);
|
||||||
|
this.on('toggleGoal', this.toggleGoal);
|
||||||
|
this.on('minimizeCanvas', this.minimizeGoal);
|
||||||
|
this.on('resizeCanvas', this.resizeGoal);
|
||||||
|
|
||||||
Level.__super__.initialize.apply(this, [options]);
|
Level.__super__.initialize.apply(this, [options]);
|
||||||
this.startOffCommand();
|
this.startOffCommand();
|
||||||
|
@ -128,7 +131,8 @@ var Level = Sandbox.extend({
|
||||||
var name = intl.getName(this.level);
|
var name = intl.getName(this.level);
|
||||||
|
|
||||||
this.levelToolbar = new LevelToolbar({
|
this.levelToolbar = new LevelToolbar({
|
||||||
name: name
|
name: name,
|
||||||
|
parent: this
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -170,7 +174,8 @@ var Level = Sandbox.extend({
|
||||||
var onlyMaster = TreeCompare.onlyMasterCompared(this.level);
|
var onlyMaster = TreeCompare.onlyMasterCompared(this.level);
|
||||||
// first we make the goal visualization holder
|
// first we make the goal visualization holder
|
||||||
this.goalCanvasHolder = new CanvasTerminalHolder({
|
this.goalCanvasHolder = new CanvasTerminalHolder({
|
||||||
text: (onlyMaster) ? intl.str('goal-only-master') : undefined
|
text: (onlyMaster) ? intl.str('goal-only-master') : undefined,
|
||||||
|
parent: this
|
||||||
});
|
});
|
||||||
|
|
||||||
// then we make a visualization. the "el" here is the element to
|
// then we make a visualization. the "el" here is the element to
|
||||||
|
@ -185,9 +190,38 @@ var Level = Sandbox.extend({
|
||||||
levelBlob: this.level,
|
levelBlob: this.level,
|
||||||
noClick: true
|
noClick: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// If the goal visualization gets dragged to the right side of the screen, then squeeze the main
|
||||||
|
// repo visualization a bit to make room. This way, you could have the goal window hang out on
|
||||||
|
// the right side of the screen and still see the repo visualization.
|
||||||
|
this.goalVis.customEvents.on('drag', _.bind(function(event, ui) {
|
||||||
|
if (ui.position.left > 0.5*$(window).width()) {
|
||||||
|
if (!$('#goalPlaceholder').is(':visible')) {
|
||||||
|
$('#goalPlaceholder').show();
|
||||||
|
this.mainVis.myResize();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($('#goalPlaceholder').is(':visible')) {
|
||||||
|
$('#goalPlaceholder').hide();
|
||||||
|
this.mainVis.myResize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, this));
|
||||||
|
|
||||||
return this.goalCanvasHolder;
|
return this.goalCanvasHolder;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
minimizeGoal: function (position, size) {
|
||||||
|
this.goalVis.hide();
|
||||||
|
this.goalWindowPos = position;
|
||||||
|
this.goalWindowSize = size;
|
||||||
|
this.levelToolbar.$goalButton.text('Show Goal');
|
||||||
|
},
|
||||||
|
|
||||||
|
resizeGoal: function () {
|
||||||
|
this.goalVis.myResize();
|
||||||
|
},
|
||||||
|
|
||||||
showSolution: function(command, deferred) {
|
showSolution: function(command, deferred) {
|
||||||
var toIssue = this.level.solutionCommand;
|
var toIssue = this.level.solutionCommand;
|
||||||
var issueFunc = _.bind(function() {
|
var issueFunc = _.bind(function() {
|
||||||
|
@ -230,8 +264,17 @@ var Level = Sandbox.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
toggleGoal: function () {
|
||||||
|
if (this.goalCanvasHolder && this.goalCanvasHolder.inDom) {
|
||||||
|
this.hideGoal();
|
||||||
|
} else {
|
||||||
|
this.showGoal();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
showGoal: function(command, defer) {
|
showGoal: function(command, defer) {
|
||||||
this.showSideVis(command, defer, this.goalCanvasHolder, this.initGoalVisualization);
|
this.showSideVis(command, defer, this.goalCanvasHolder, this.initGoalVisualization);
|
||||||
|
this.levelToolbar.$goalButton.text('Hide Goal');
|
||||||
},
|
},
|
||||||
|
|
||||||
showSideVis: function(command, defer, canvasHolder, initMethod) {
|
showSideVis: function(command, defer, canvasHolder, initMethod) {
|
||||||
|
@ -242,12 +285,13 @@ var Level = Sandbox.extend({
|
||||||
canvasHolder = initMethod.apply(this);
|
canvasHolder = initMethod.apply(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
canvasHolder.slideIn();
|
canvasHolder.restore(this.goalWindowPos, this.goalWindowSize);
|
||||||
setTimeout(safeFinish, canvasHolder.getAnimationTime());
|
setTimeout(safeFinish, canvasHolder.getAnimationTime());
|
||||||
},
|
},
|
||||||
|
|
||||||
hideGoal: function(command, defer) {
|
hideGoal: function(command, defer) {
|
||||||
this.hideSideVis(command, defer, this.goalCanvasHolder);
|
this.hideSideVis(command, defer, this.goalCanvasHolder);
|
||||||
|
this.levelToolbar.$goalButton.text('Show Goal');
|
||||||
},
|
},
|
||||||
|
|
||||||
hideSideVis: function(command, defer, canvasHolder, vis) {
|
hideSideVis: function(command, defer, canvasHolder, vis) {
|
||||||
|
|
|
@ -558,6 +558,7 @@ var LevelToolbar = BaseView.extend({
|
||||||
|
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
this.parent = options.parent;
|
||||||
this.JSON = {
|
this.JSON = {
|
||||||
name: options.name || 'Some level! (unknown name)'
|
name: options.name || 'Some level! (unknown name)'
|
||||||
};
|
};
|
||||||
|
@ -565,6 +566,13 @@ var LevelToolbar = BaseView.extend({
|
||||||
this.beforeDestination = $($('#commandLineHistory div.toolbar')[0]);
|
this.beforeDestination = $($('#commandLineHistory div.toolbar')[0]);
|
||||||
this.render();
|
this.render();
|
||||||
|
|
||||||
|
this.$goalButton = this.$el.find('#show-goal');
|
||||||
|
|
||||||
|
var parent = this.parent;
|
||||||
|
this.$goalButton.on('click', function () {
|
||||||
|
parent.trigger('toggleGoal');
|
||||||
|
});
|
||||||
|
|
||||||
if (!options.wait) {
|
if (!options.wait) {
|
||||||
process.nextTick(_.bind(this.show, this));
|
process.nextTick(_.bind(this.show, this));
|
||||||
}
|
}
|
||||||
|
@ -840,6 +848,8 @@ var CanvasTerminalHolder = BaseView.extend({
|
||||||
|
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
this.parent = options.parent;
|
||||||
|
this.minHeight = options.minHeight || 200;
|
||||||
this.destination = $('body');
|
this.destination = $('body');
|
||||||
this.JSON = {
|
this.JSON = {
|
||||||
title: options.title || intl.str('goal-to-reach'),
|
title: options.title || intl.str('goal-to-reach'),
|
||||||
|
@ -849,6 +859,19 @@ var CanvasTerminalHolder = BaseView.extend({
|
||||||
this.render();
|
this.render();
|
||||||
this.inDom = true;
|
this.inDom = true;
|
||||||
|
|
||||||
|
this.$terminal = this.$el.find('.terminal-window-holder').first();
|
||||||
|
this.$terminal.height(0.8 * $(window).height());
|
||||||
|
this.$terminal.draggable({
|
||||||
|
cursor: 'move',
|
||||||
|
handle: '.toolbar',
|
||||||
|
containment: '#interfaceWrapper',
|
||||||
|
scroll: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// If the entire window gets resized such that the terminal is outside the view, then
|
||||||
|
// move it back into the view, and expand/shrink it vertically as necessary.
|
||||||
|
$(window).on('resize', _.debounce(_.bind(this.recalcLayout, this), 300));
|
||||||
|
|
||||||
if (options.additionalClass) {
|
if (options.additionalClass) {
|
||||||
this.$el.addClass(options.additionalClass);
|
this.$el.addClass(options.additionalClass);
|
||||||
}
|
}
|
||||||
|
@ -861,7 +884,7 @@ var CanvasTerminalHolder = BaseView.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
die: function() {
|
die: function() {
|
||||||
this.slideOut();
|
this.minimize();
|
||||||
this.inDom = false;
|
this.inDom = false;
|
||||||
|
|
||||||
setTimeout(_.bind(function() {
|
setTimeout(_.bind(function() {
|
||||||
|
@ -869,16 +892,79 @@ var CanvasTerminalHolder = BaseView.extend({
|
||||||
}, this), this.getAnimationTime());
|
}, this), this.getAnimationTime());
|
||||||
},
|
},
|
||||||
|
|
||||||
slideOut: function() {
|
minimize: function() {
|
||||||
this.slideToggle(true);
|
this.parent.trigger('minimizeCanvas', {
|
||||||
|
left: this.$terminal.css('left'),
|
||||||
|
top: this.$terminal.css('top')
|
||||||
|
}, {
|
||||||
|
width: this.$terminal.css('width'),
|
||||||
|
height: this.$terminal.css('height')
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$terminal.animate({
|
||||||
|
height: '0px',
|
||||||
|
opacity: 0
|
||||||
|
}, this.getAnimationTime());
|
||||||
},
|
},
|
||||||
|
|
||||||
slideIn: function() {
|
restore: function (pos, size) {
|
||||||
this.slideToggle(false);
|
var self = this;
|
||||||
|
pos = pos || { top: this.$terminal.css('top'), left: this.$terminal.css('left') };
|
||||||
|
size = size || { width: this.$terminal.css('width'), height: this.$terminal.css('height') };
|
||||||
|
|
||||||
|
this.$terminal.css({
|
||||||
|
top: pos.top,
|
||||||
|
left: pos.left,
|
||||||
|
width: size.width,
|
||||||
|
height: '0px',
|
||||||
|
opacity: '0'
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$terminal.animate({
|
||||||
|
height: size.height,
|
||||||
|
opacity: 1
|
||||||
|
}, this.getAnimationTime(), function () {
|
||||||
|
self.recalcLayout();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
slideToggle: function(value) {
|
recalcLayout: function () {
|
||||||
this.$('div.terminal-window-holder').toggleClass('slideOut', value);
|
// Resize/reposition self based on the size of the browser window.
|
||||||
|
|
||||||
|
var parent = this.parent,
|
||||||
|
leftOffset = 0,
|
||||||
|
topOffset = 0,
|
||||||
|
heightOffset = 0,
|
||||||
|
width = this.$terminal.outerWidth(),
|
||||||
|
height = this.$terminal.outerHeight(),
|
||||||
|
left = this.$terminal.offset().left,
|
||||||
|
top = this.$terminal.offset().top,
|
||||||
|
right = ($(window).width() - (left + width)),
|
||||||
|
bottom = ($(window).height() - (top + height)),
|
||||||
|
minHeight = 0.75 * $(window).height(),
|
||||||
|
maxHeight = 0.95 * $(window).height();
|
||||||
|
|
||||||
|
// Calculate offsets
|
||||||
|
if (top < 0) { topOffset = -top; }
|
||||||
|
if (left < 0) { leftOffset = -left; }
|
||||||
|
if (right < 0) { leftOffset = right; }
|
||||||
|
if (bottom < 0) { topOffset = bottom; }
|
||||||
|
if (height < minHeight) { heightOffset = minHeight - height; }
|
||||||
|
if (height > maxHeight) { heightOffset = maxHeight - height; }
|
||||||
|
|
||||||
|
// Establish limits
|
||||||
|
left = Math.max(left + leftOffset, 0);
|
||||||
|
top = Math.max(top + topOffset, 0);
|
||||||
|
height = Math.max(height + heightOffset, minHeight);
|
||||||
|
|
||||||
|
// Set the new position/size
|
||||||
|
this.$terminal.animate({
|
||||||
|
left: left + 'px',
|
||||||
|
top: top + 'px',
|
||||||
|
height: height + 'px'
|
||||||
|
}, this.getAnimationTime(), function () {
|
||||||
|
parent.trigger('resizeCanvas');
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getCanvasLocation: function() {
|
getCanvasLocation: function() {
|
||||||
|
|
|
@ -74,6 +74,13 @@ var Visualization = Backbone.View.extend({
|
||||||
this.myResize();
|
this.myResize();
|
||||||
}, this));
|
}, this));
|
||||||
|
|
||||||
|
// If the visualization is within a draggable container, we need to update the
|
||||||
|
// position whenever the container is moved.
|
||||||
|
this.$el.parents('.ui-draggable').on('drag', _.bind(function(event, ui) {
|
||||||
|
this.customEvents.trigger('drag', event, ui);
|
||||||
|
this.myResize();
|
||||||
|
}, this));
|
||||||
|
|
||||||
this.gitVisuals.drawTreeFirstTime();
|
this.gitVisuals.drawTreeFirstTime();
|
||||||
if (this.treeString) {
|
if (this.treeString) {
|
||||||
this.gitEngine.loadTreeFromString(this.treeString);
|
this.gitEngine.loadTreeFromString(this.treeString);
|
||||||
|
@ -182,12 +189,14 @@ var Visualization = Backbone.View.extend({
|
||||||
$(this.paper.canvas).css('visibility', 'visible');
|
$(this.paper.canvas).css('visibility', 'visible');
|
||||||
setTimeout(_.bind(this.fadeTreeIn, this), 10);
|
setTimeout(_.bind(this.fadeTreeIn, this), 10);
|
||||||
this.originToo('show', arguments);
|
this.originToo('show', arguments);
|
||||||
|
this.myResize();
|
||||||
},
|
},
|
||||||
|
|
||||||
showHarsh: function() {
|
showHarsh: function() {
|
||||||
$(this.paper.canvas).css('visibility', 'visible');
|
$(this.paper.canvas).css('visibility', 'visible');
|
||||||
this.setTreeOpacity(1);
|
this.setTreeOpacity(1);
|
||||||
this.originToo('showHarsh', arguments);
|
this.originToo('showHarsh', arguments);
|
||||||
|
this.myResize();
|
||||||
},
|
},
|
||||||
|
|
||||||
resetFromThisTreeNow: function(treeString) {
|
resetFromThisTreeNow: function(treeString) {
|
||||||
|
@ -257,8 +266,8 @@ var Visualization = Backbone.View.extend({
|
||||||
// if we don't have a container, we need to set our
|
// if we don't have a container, we need to set our
|
||||||
// position absolutely to whatever we are tracking
|
// position absolutely to whatever we are tracking
|
||||||
if (!this.containerElement) {
|
if (!this.containerElement) {
|
||||||
var left = el.offsetLeft;
|
var left = this.$el.offset().left;
|
||||||
var top = el.offsetTop;
|
var top = this.$el.offset().top;
|
||||||
|
|
||||||
$(this.paper.canvas).css({
|
$(this.paper.canvas).css({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
|
|
@ -34,7 +34,7 @@ p {
|
||||||
}
|
}
|
||||||
|
|
||||||
.githubLink {
|
.githubLink {
|
||||||
z-index: 99;
|
z-index: 2;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
@ -224,10 +224,11 @@ body.hgMode #mainVisSpace .modeText.hgMode {
|
||||||
/* Some interface things */
|
/* Some interface things */
|
||||||
|
|
||||||
div.canvasTerminalHolder {
|
div.canvasTerminalHolder {
|
||||||
height: 100%;
|
height: 0;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
z-index: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
#canvasHolder {
|
#canvasHolder {
|
||||||
|
@ -254,28 +255,8 @@ body.hgMode .visBackgroundColor {
|
||||||
min-height: 600px;
|
min-height: 600px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.canvasTerminalHolder > div.terminal-window-holder {
|
|
||||||
margin: 100px 0;
|
|
||||||
height: 100%;
|
|
||||||
-webkit-transform: translate3d(0,0,0);
|
|
||||||
-moz-transform: translate3d(0,0,0);
|
|
||||||
-o-transform: translate3d(0,0,0);
|
|
||||||
-ms-transform: translate3d(0,0,0);
|
|
||||||
transform: translate3d(0,0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
div.canvasTerminalHolder > div.terminal-window-holder.slideOut {
|
|
||||||
-webkit-transform: translate3d(-150%,0,0);
|
|
||||||
-moz-transform: translate3d(-150%,0,0);
|
|
||||||
-o-transform: translate3d(-150%,0,0);
|
|
||||||
-ms-transform: translate3d(-150%,0,0);
|
|
||||||
transform: translate3d(-150%,0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
div.canvasTerminalHolder > div.terminal-window-holder > div.wrapper {
|
div.canvasTerminalHolder > div.terminal-window-holder > div.wrapper {
|
||||||
margin: 0 20px 0px 20px;
|
height: 100%;
|
||||||
height: 80%;
|
|
||||||
box-shadow: 0 0 30px rgb(0,0,0);
|
box-shadow: 0 0 30px rgb(0,0,0);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 0 0 5px 5px;
|
border-radius: 0 0 5px 5px;
|
||||||
|
@ -346,6 +327,21 @@ div.toolbar.level-toolbar {
|
||||||
background-image: linear-gradient(top, #B2FF2E, #8AD247);
|
background-image: linear-gradient(top, #B2FF2E, #8AD247);
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toolbar.level-toolbar button {
|
||||||
|
font-size: 12px;
|
||||||
|
border: 1px solid #888;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
background-image: -webkit-linear-gradient(top, #EFEDEE, #C1C1C1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#show-goal {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.levelToolbarSpan {
|
span.levelToolbarSpan {
|
||||||
|
@ -739,6 +735,10 @@ div.modalView.box.inFront.show {
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.terminal-window-holder {
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
.terminal-window .inside {
|
.terminal-window .inside {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.7);
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.7);
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="mainVisSpace" class="box flex1 horizontal transitionAll visBackgroundColor">
|
<div id="mainVisSpace" class="box flex2 horizontal transitionAll visBackgroundColor">
|
||||||
<span class="modeText transitionOpacity gitMode">
|
<span class="modeText transitionOpacity gitMode">
|
||||||
Git
|
Git
|
||||||
</span>
|
</span>
|
||||||
|
@ -75,6 +75,12 @@
|
||||||
Hg
|
Hg
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- If you drag the goal window to the right side of the screen, this gets shown and causes
|
||||||
|
the main visualization to squeeze a bit. This way, you could have the goal window hang out
|
||||||
|
on the right side of the screen and still see the repo visualization. -->
|
||||||
|
<div id="goalPlaceholder" class="box flex1 visBackgroundColor" style="display: none;"></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="canvasHolder">
|
<div id="canvasHolder">
|
||||||
|
@ -138,6 +144,7 @@
|
||||||
<script type="text/html" id="level-toolbar-template">
|
<script type="text/html" id="level-toolbar-template">
|
||||||
<div class="toolbar level-toolbar box vertical center transitionAll hidden">
|
<div class="toolbar level-toolbar box vertical center transitionAll hidden">
|
||||||
<div>
|
<div>
|
||||||
|
<button id="show-goal" type="button">Show Goal</button>
|
||||||
<i class="icon-bolt"></i>
|
<i class="icon-bolt"></i>
|
||||||
Level
|
Level
|
||||||
<span class="levelToolbarSpan">
|
<span class="levelToolbarSpan">
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue