Support dragging the goal window

This commit is contained in:
Sergey Krilov 2014-03-09 20:46:30 -04:00
parent 549e67b1c7
commit f29252e6ad
5 changed files with 182 additions and 36 deletions

View file

@ -50,6 +50,9 @@ var Level = Sandbox.extend({
this.initGoalData(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]);
this.startOffCommand();
@ -128,7 +131,8 @@ var Level = Sandbox.extend({
var name = intl.getName(this.level);
this.levelToolbar = new LevelToolbar({
name: name
name: name,
parent: this
});
},
@ -170,7 +174,8 @@ var Level = Sandbox.extend({
var onlyMaster = TreeCompare.onlyMasterCompared(this.level);
// first we make the goal visualization holder
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
@ -185,9 +190,38 @@ var Level = Sandbox.extend({
levelBlob: this.level,
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;
},
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) {
var toIssue = this.level.solutionCommand;
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) {
this.showSideVis(command, defer, this.goalCanvasHolder, this.initGoalVisualization);
this.levelToolbar.$goalButton.text('Hide Goal');
},
showSideVis: function(command, defer, canvasHolder, initMethod) {
@ -242,12 +285,13 @@ var Level = Sandbox.extend({
canvasHolder = initMethod.apply(this);
}
canvasHolder.slideIn();
canvasHolder.restore(this.goalWindowPos, this.goalWindowSize);
setTimeout(safeFinish, canvasHolder.getAnimationTime());
},
hideGoal: function(command, defer) {
this.hideSideVis(command, defer, this.goalCanvasHolder);
this.levelToolbar.$goalButton.text('Show Goal');
},
hideSideVis: function(command, defer, canvasHolder, vis) {

View file

@ -558,6 +558,7 @@ var LevelToolbar = BaseView.extend({
initialize: function(options) {
options = options || {};
this.parent = options.parent;
this.JSON = {
name: options.name || 'Some level! (unknown name)'
};
@ -565,6 +566,13 @@ var LevelToolbar = BaseView.extend({
this.beforeDestination = $($('#commandLineHistory div.toolbar')[0]);
this.render();
this.$goalButton = this.$el.find('#show-goal');
var parent = this.parent;
this.$goalButton.on('click', function () {
parent.trigger('toggleGoal');
});
if (!options.wait) {
process.nextTick(_.bind(this.show, this));
}
@ -840,6 +848,8 @@ var CanvasTerminalHolder = BaseView.extend({
initialize: function(options) {
options = options || {};
this.parent = options.parent;
this.minHeight = options.minHeight || 200;
this.destination = $('body');
this.JSON = {
title: options.title || intl.str('goal-to-reach'),
@ -849,6 +859,19 @@ var CanvasTerminalHolder = BaseView.extend({
this.render();
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) {
this.$el.addClass(options.additionalClass);
}
@ -861,7 +884,7 @@ var CanvasTerminalHolder = BaseView.extend({
},
die: function() {
this.slideOut();
this.minimize();
this.inDom = false;
setTimeout(_.bind(function() {
@ -869,16 +892,79 @@ var CanvasTerminalHolder = BaseView.extend({
}, this), this.getAnimationTime());
},
slideOut: function() {
this.slideToggle(true);
minimize: function() {
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() {
this.slideToggle(false);
restore: function (pos, size) {
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) {
this.$('div.terminal-window-holder').toggleClass('slideOut', value);
recalcLayout: function () {
// 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() {

View file

@ -74,6 +74,13 @@ var Visualization = Backbone.View.extend({
this.myResize();
}, 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();
if (this.treeString) {
this.gitEngine.loadTreeFromString(this.treeString);
@ -182,12 +189,14 @@ var Visualization = Backbone.View.extend({
$(this.paper.canvas).css('visibility', 'visible');
setTimeout(_.bind(this.fadeTreeIn, this), 10);
this.originToo('show', arguments);
this.myResize();
},
showHarsh: function() {
$(this.paper.canvas).css('visibility', 'visible');
this.setTreeOpacity(1);
this.originToo('showHarsh', arguments);
this.myResize();
},
resetFromThisTreeNow: function(treeString) {
@ -257,8 +266,8 @@ var Visualization = Backbone.View.extend({
// if we don't have a container, we need to set our
// position absolutely to whatever we are tracking
if (!this.containerElement) {
var left = el.offsetLeft;
var top = el.offsetTop;
var left = this.$el.offset().left;
var top = this.$el.offset().top;
$(this.paper.canvas).css({
position: 'absolute',

View file

@ -34,7 +34,7 @@ p {
}
.githubLink {
z-index: 99;
z-index: 2;
position: fixed;
top: 0;
right: 0;
@ -224,10 +224,11 @@ body.hgMode #mainVisSpace .modeText.hgMode {
/* Some interface things */
div.canvasTerminalHolder {
height: 100%;
height: 0;
position: fixed;
top: 0;
left: 0;
z-index: 3;
}
#canvasHolder {
@ -254,28 +255,8 @@ body.hgMode .visBackgroundColor {
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 {
margin: 0 20px 0px 20px;
height: 80%;
height: 100%;
box-shadow: 0 0 30px rgb(0,0,0);
cursor: pointer;
border-radius: 0 0 5px 5px;
@ -346,6 +327,21 @@ div.toolbar.level-toolbar {
background-image: linear-gradient(top, #B2FF2E, #8AD247);
border-radius: 0;
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 {
@ -739,6 +735,10 @@ div.modalView.box.inFront.show {
z-index: 100;
}
.terminal-window-holder {
z-index: 3;
}
.terminal-window .inside {
padding: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.7);

View file

@ -67,7 +67,7 @@
</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">
Git
</span>
@ -75,6 +75,12 @@
Hg
</span>
</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 id="canvasHolder">
@ -138,6 +144,7 @@
<script type="text/html" id="level-toolbar-template">
<div class="toolbar level-toolbar box vertical center transitionAll hidden">
<div>
<button id="show-goal" type="button">Show Goal</button>
<i class="icon-bolt"></i>
Level
<span class="levelToolbarSpan">