Bug 712096 - Exiting 3D (Tilt) mode of the developer tools should show a transition back to a flat page; r=rcampbell

This commit is contained in:
Victor Porof 2012-01-16 09:00:56 +02:00
Родитель 0e5a9fda69
Коммит 8b15781bd3
3 изменённых файлов: 148 добавлений и 60 удалений

Просмотреть файл

@ -100,7 +100,7 @@ Tilt.prototype = {
// if the visualizer for the current tab is already open, destroy it now // if the visualizer for the current tab is already open, destroy it now
if (this.visualizers[id]) { if (this.visualizers[id]) {
this.destroy(id); this.destroy(id, true);
return; return;
} }
@ -126,20 +126,42 @@ Tilt.prototype = {
* *
* @param {String} aId * @param {String} aId
* the identifier of the instance in the visualizers array * the identifier of the instance in the visualizers array
* @param {Boolean} aAnimateFlag
* optional, set to true to display a destruction transition
*/ */
destroy: function T_destroy(aId) destroy: function T_destroy(aId, aAnimateFlag)
{ {
// if the visualizer is already destroyed, don't do anything // if the visualizer is already destroyed, don't do anything
if (!this.visualizers[aId]) { if (!this.visualizers[aId]) {
return; return;
} }
this.visualizers[aId].removeOverlay(); if (!this.isDestroying) {
this.visualizers[aId].cleanup(); this.isDestroying = true;
this.visualizers[aId] = null;
this.chromeWindow.gBrowser.selectedBrowser.contentWindow.focus(); let finalize = function T_finalize(aId) {
Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.DESTROYED, null); this.visualizers[aId].removeOverlay();
this.visualizers[aId].cleanup();
this.visualizers[aId] = null;
this.isDestroying = false;
this.chromeWindow.gBrowser.selectedBrowser.focus();
Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.DESTROYED, null);
};
if (!aAnimateFlag) {
finalize.call(this, aId);
return;
}
let controller = this.visualizers[aId].controller;
let presenter = this.visualizers[aId].presenter;
let content = presenter.contentWindow;
controller.removeEventListeners();
controller.arcball.reset([-content.pageXOffset, -content.pageYOffset]);
presenter.executeDestruction(finalize.bind(this, aId));
}
}, },
/** /**

Просмотреть файл

@ -60,7 +60,8 @@ const INVISIBLE_ELEMENTS = {
const STACK_THICKNESS = 15; const STACK_THICKNESS = 15;
const WIREFRAME_COLOR = [0, 0, 0, 0.25]; const WIREFRAME_COLOR = [0, 0, 0, 0.25];
const INITIAL_TRANSITION_DURATION = 100; const INTRO_TRANSITION_DURATION = 80;
const OUTRO_TRANSITION_DURATION = 50;
const INITIAL_Z_TRANSLATION = 400; const INITIAL_Z_TRANSLATION = 400;
const MOUSE_CLICK_THRESHOLD = 10; const MOUSE_CLICK_THRESHOLD = 10;
@ -297,6 +298,16 @@ TiltVisualizer.Presenter = function TV_Presenter(
if ("function" === typeof this.ondraw) { if ("function" === typeof this.ondraw) {
this.ondraw(); this.ondraw();
} }
if ("function" === typeof this.onInitializationFinished &&
this.frames === INTRO_TRANSITION_DURATION &&
!this.isExecutingDestruction) {
this.onInitializationFinished();
}
if ("function" === typeof this.onDestructionFinished &&
this.frames === OUTRO_TRANSITION_DURATION &&
this.isExecutingDestruction) {
this.onDestructionFinished();
}
}.bind(this); }.bind(this);
setup(); setup();
@ -312,6 +323,8 @@ TiltVisualizer.Presenter.prototype = {
{ {
let renderer = this.renderer; let renderer = this.renderer;
let transforms = this.transforms; let transforms = this.transforms;
let w = renderer.width;
let h = renderer.height;
// if the mesh wasn't created yet, don't continue rendering // if the mesh wasn't created yet, don't continue rendering
if (!this.meshStacks || !this.meshWireframe) { if (!this.meshStacks || !this.meshWireframe) {
@ -323,10 +336,15 @@ TiltVisualizer.Presenter.prototype = {
renderer.perspective(); renderer.perspective();
// apply a transition transformation using an ortho and perspective matrix // apply a transition transformation using an ortho and perspective matrix
let f = this.frames / INITIAL_TRANSITION_DURATION; let ortho = mat4.ortho(0, w, h, 0, -1000, 1000);
let w = renderer.width;
let h = renderer.height; if (!this.isExecutingDestruction) {
renderer.lerp(renderer.projMatrix, mat4.ortho(0, w, h, 0, -1, 1000), f, 8); let f = this.frames / INTRO_TRANSITION_DURATION;
renderer.lerp(renderer.projMatrix, ortho, f, 8);
} else {
let f = this.frames / OUTRO_TRANSITION_DURATION;
renderer.lerp(renderer.projMatrix, ortho, 1 - f, 8);
}
// apply the preliminary transformations to the model view // apply the preliminary transformations to the model view
renderer.translate(w * 0.5, h * 0.5, -INITIAL_Z_TRANSLATION); renderer.translate(w * 0.5, h * 0.5, -INITIAL_Z_TRANSLATION);
@ -351,7 +369,8 @@ TiltVisualizer.Presenter.prototype = {
this.drawHighlight(); this.drawHighlight();
// make sure the initial transition is drawn until finished // make sure the initial transition is drawn until finished
if (this.frames < INITIAL_TRANSITION_DURATION) { if (this.frames < INTRO_TRANSITION_DURATION ||
this.frames < OUTRO_TRANSITION_DURATION) {
this.redraw = true; this.redraw = true;
} }
this.frames++; this.frames++;
@ -670,7 +689,8 @@ TiltVisualizer.Presenter.prototype = {
vec3.set([x, y + h, z * STACK_THICKNESS], highlight.v3); vec3.set([x, y + h, z * STACK_THICKNESS], highlight.v3);
this._currentSelection = aNodeIndex; this._currentSelection = aNodeIndex;
this.inspectorUI.inspectNode(node); this.inspectorUI.inspectNode(node, this.contentWindow.innerHeight < y ||
this.contentWindow.pageYOffset > 0);
}, },
/** /**
@ -789,6 +809,28 @@ TiltVisualizer.Presenter.prototype = {
return this.renderer && this.renderer.context; return this.renderer && this.renderer.context;
}, },
/**
* Starts executing a destruction animation and executes a callback function
* when finished.
*
* @param {Function} aCallback
* the destruction finished callback
*/
executeDestruction: function TV_executeDestruction(aCallback)
{
if (!this.isExecutingDestruction) {
this.isExecutingDestruction = true;
this.onDestructionFinished = aCallback;
if (this.frames > OUTRO_TRANSITION_DURATION) {
this.frames = 0;
this.redraw = true;
} else {
aCallback();
}
}
},
/** /**
* Function called when this object is destroyed. * Function called when this object is destroyed.
*/ */
@ -853,20 +895,8 @@ TiltVisualizer.Controller = function TV_Controller(aCanvas, aPresenter)
TiltUtils.bindObjectFunc(this, "update"); TiltUtils.bindObjectFunc(this, "update");
TiltUtils.bindObjectFunc(this, "^on"); TiltUtils.bindObjectFunc(this, "^on");
// bind commonly used mouse and keyboard events with the controller // add the necessary event listeners
aCanvas.addEventListener("mousedown", this.onMouseDown, false); this.addEventListeners();
aCanvas.addEventListener("mouseup", this.onMouseUp, false);
aCanvas.addEventListener("click", this.onMouseClick, false);
aCanvas.addEventListener("mousemove", this.onMouseMove, false);
aCanvas.addEventListener("mouseover", this.onMouseOver, false);
aCanvas.addEventListener("mouseout", this.onMouseOut, false);
aCanvas.addEventListener("MozMousePixelScroll", this.onMozScroll, false);
aCanvas.addEventListener("keydown", this.onKeyDown, false);
aCanvas.addEventListener("keyup", this.onKeyUp, false);
aCanvas.addEventListener("blur", this.onBlur, false);
// handle resize events to change the arcball dimensions
aPresenter.contentWindow.addEventListener("resize", this.onResize, false);
// attach this controller's update function to the presenter ondraw event // attach this controller's update function to the presenter ondraw event
aPresenter.ondraw = this.update; aPresenter.ondraw = this.update;
@ -874,6 +904,52 @@ TiltVisualizer.Controller = function TV_Controller(aCanvas, aPresenter)
TiltVisualizer.Controller.prototype = { TiltVisualizer.Controller.prototype = {
/**
* Adds all added events listeners required by this controller.
*/
addEventListeners: function TVC_addEventListeners()
{
let canvas = this.canvas;
let presenter = this.presenter;
// bind commonly used mouse and keyboard events with the controller
canvas.addEventListener("mousedown", this.onMouseDown, false);
canvas.addEventListener("mouseup", this.onMouseUp, false);
canvas.addEventListener("click", this.onMouseClick, false);
canvas.addEventListener("mousemove", this.onMouseMove, false);
canvas.addEventListener("mouseover", this.onMouseOver, false);
canvas.addEventListener("mouseout", this.onMouseOut, false);
canvas.addEventListener("MozMousePixelScroll", this.onMozScroll, false);
canvas.addEventListener("keydown", this.onKeyDown, false);
canvas.addEventListener("keyup", this.onKeyUp, false);
canvas.addEventListener("blur", this.onBlur, false);
// handle resize events to change the arcball dimensions
presenter.contentWindow.addEventListener("resize", this.onResize, false);
},
/**
* Removes all added events listeners required by this controller.
*/
removeEventListeners: function TVC_removeEventListeners()
{
let canvas = this.canvas;
let presenter = this.presenter;
canvas.removeEventListener("mousedown", this.onMouseDown, false);
canvas.removeEventListener("mouseup", this.onMouseUp, false);
canvas.removeEventListener("click", this.onMouseClick, false);
canvas.removeEventListener("mousemove", this.onMouseMove, false);
canvas.removeEventListener("mouseover", this.onMouseOver, false);
canvas.removeEventListener("mouseout", this.onMouseOut, false);
canvas.removeEventListener("MozMousePixelScroll", this.onMozScroll, false);
canvas.removeEventListener("keydown", this.onKeyDown, false);
canvas.removeEventListener("keyup", this.onKeyUp, false);
canvas.removeEventListener("blur", this.onBlur, false);
presenter.contentWindow.removeEventListener("resize", this.onResize,false);
},
/** /**
* Function called each frame, updating the visualization camera transforms. * Function called each frame, updating the visualization camera transforms.
*/ */
@ -1011,7 +1087,7 @@ TiltVisualizer.Controller.prototype = {
let code = e.keyCode || e.which; let code = e.keyCode || e.which;
if (code === e.DOM_VK_ESCAPE) { if (code === e.DOM_VK_ESCAPE) {
this.presenter.tiltUI.destroy(this.presenter.tiltUI.currentWindowId); this.presenter.tiltUI.destroy(this.presenter.tiltUI.currentWindowId, 1);
return; return;
} }
@ -1056,24 +1132,11 @@ TiltVisualizer.Controller.prototype = {
*/ */
finalize: function TVC_finalize() finalize: function TVC_finalize()
{ {
let canvas = this.canvas;
let presenter = this.presenter;
TiltUtils.destroyObject(this.arcball); TiltUtils.destroyObject(this.arcball);
TiltUtils.destroyObject(this.coordinates); TiltUtils.destroyObject(this.coordinates);
canvas.removeEventListener("mousedown", this.onMouseDown, false); this.removeEventListeners();
canvas.removeEventListener("mouseup", this.onMouseUp, false); this.presenter.ondraw = null;
canvas.removeEventListener("click", this.onMouseClick, false);
canvas.removeEventListener("mousemove", this.onMouseMove, false);
canvas.removeEventListener("mouseover", this.onMouseOver, false);
canvas.removeEventListener("mouseout", this.onMouseOut, false);
canvas.removeEventListener("MozMousePixelScroll", this.onMozScroll, false);
canvas.removeEventListener("keydown", this.onKeyDown, false);
canvas.removeEventListener("keyup", this.onKeyUp, false);
canvas.removeEventListener("blur", this.onBlur, false);
presenter.contentWindow.removeEventListener("resize", this.onResize,false);
presenter.ondraw = null;
} }
}; };

Просмотреть файл

@ -30,6 +30,7 @@ function createNewTab() {
tab0 = gBrowser.selectedTab; tab0 = gBrowser.selectedTab;
tab1 = createTab(function() { tab1 = createTab(function() {
Services.obs.addObserver(cleanup, TILT_DESTROYED, false);
Services.obs.addObserver(tab_TILT_INITIALIZED, TILT_INITIALIZED, false); Services.obs.addObserver(tab_TILT_INITIALIZED, TILT_INITIALIZED, false);
Services.obs.addObserver(tab_TILT_DESTROYED, TILT_DESTROYED, false); Services.obs.addObserver(tab_TILT_DESTROYED, TILT_DESTROYED, false);
Services.obs.addObserver(tab_TILT_SHOWN, TILT_SHOWN, false); Services.obs.addObserver(tab_TILT_SHOWN, TILT_SHOWN, false);
@ -70,25 +71,27 @@ let testSteps = [
}, },
function step2() { function step2() {
Tilt.destroy(Tilt.currentWindowId); Tilt.destroy(Tilt.currentWindowId);
Services.obs.removeObserver(tab_TILT_INITIALIZED, TILT_INITIALIZED, false);
Services.obs.removeObserver(tab_TILT_DESTROYED, TILT_DESTROYED, false);
Services.obs.removeObserver(tab_TILT_SHOWN, TILT_SHOWN, false);
Services.obs.removeObserver(tab_TILT_HIDDEN, TILT_HIDDEN, false);
gBrowser.removeCurrentTab();
},
function step3_cleanup() {
is(tabEvents, "ti;th;ts;td;",
"The notifications weren't fired in the correct order.");
tab0 = null;
tab1 = null;
gBrowser.tabContainer.removeEventListener("TabSelect", tabSelect, false);
finish();
} }
]; ];
function cleanup() {
is(tabEvents, "ti;th;ts;td;",
"The notifications weren't fired in the correct order.");
tab0 = null;
tab1 = null;
Services.obs.removeObserver(cleanup, TILT_DESTROYED);
Services.obs.removeObserver(tab_TILT_INITIALIZED, TILT_INITIALIZED, false);
Services.obs.removeObserver(tab_TILT_DESTROYED, TILT_DESTROYED, false);
Services.obs.removeObserver(tab_TILT_SHOWN, TILT_SHOWN, false);
Services.obs.removeObserver(tab_TILT_HIDDEN, TILT_HIDDEN, false);
gBrowser.tabContainer.removeEventListener("TabSelect", tabSelect, false);
gBrowser.removeCurrentTab();
finish();
}
function tabSelect() { function tabSelect() {
if (testStep !== -1) { if (testStep !== -1) {
executeSoon(testSteps[testStep]); executeSoon(testSteps[testStep]);