This commit is contained in:
Tim Taubert 2012-02-13 10:44:02 +01:00
Родитель 7558e838d3 f56a4e3f0e
Коммит 8307497987
22 изменённых файлов: 455 добавлений и 85 удалений

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

@ -40,8 +40,6 @@
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
"use strict"; "use strict";
/*global Components, NetUtil, Services, XPCOMUtils */
/*global DebuggerServer, DebuggerClient, SourceEditor */
const Cc = Components.classes; const Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
const Cu = Components.utils; const Cu = Components.utils;
@ -295,7 +293,7 @@ DebuggerUI.prototype = {
return this.logError(url, aStatusCode); return this.logError(url, aStatusCode);
} }
this._onSourceLoaded(url, chunks.join("")); this._onSourceLoaded(url, chunks.join(""), channel.contentType);
}.bind(this) }.bind(this)
}; };
@ -325,14 +323,14 @@ DebuggerUI.prototype = {
* The URL of the source script. * The URL of the source script.
* @param string aSourceText * @param string aSourceText
* The text of the source script. * The text of the source script.
* @param string aContentType
* The content type of the source script.
*/ */
_onSourceLoaded: function DebuggerUI__onSourceLoaded(aSourceUrl, aSourceText) { _onSourceLoaded: function DebuggerUI__onSourceLoaded(aSourceUrl,
aSourceText,
aContentType) {
let dbg = this.getDebugger(this.aWindow.gBrowser.selectedTab); let dbg = this.getDebugger(this.aWindow.gBrowser.selectedTab);
if (aSourceUrl.slice(-3) == ".js") { dbg.debuggerWindow.SourceScripts.setEditorMode(aSourceUrl, aContentType);
dbg.editor.setMode(SourceEditor.MODES.JAVASCRIPT);
} else {
dbg.editor.setMode(SourceEditor.MODES.HTML);
}
dbg.editor.setText(aSourceText); dbg.editor.setText(aSourceText);
let doc = dbg.frame.contentDocument; let doc = dbg.frame.contentDocument;
let scripts = doc.getElementById("scripts"); let scripts = doc.getElementById("scripts");
@ -340,6 +338,7 @@ DebuggerUI.prototype = {
let script = elt.getUserData("sourceScript"); let script = elt.getUserData("sourceScript");
script.loaded = true; script.loaded = true;
script.text = aSourceText; script.text = aSourceText;
script.contentType = aContentType;
elt.setUserData("sourceScript", script, null); elt.setUserData("sourceScript", script, null);
} }
}; };

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

@ -38,9 +38,7 @@
***** END LICENSE BLOCK *****/ ***** END LICENSE BLOCK *****/
"use strict"; "use strict";
/*global Components, XPCOMUtils, Services, StackFrames, ThreadState, dump */
const Cu = Components.utils; const Cu = Components.utils;
const DBG_STRINGS_URI = "chrome://browser/locale/devtools/debugger.properties"; const DBG_STRINGS_URI = "chrome://browser/locale/devtools/debugger.properties";
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@ -1070,6 +1068,49 @@ DebuggerView.Scripts = {
} }
}, },
/**
* Checks whether the script with the specified URL is among the scripts
* known to the debugger and shown in the list.
*
* @param string aUrl
* The script URL.
*/
contains: function DVS_contains(aUrl) {
if (this._scripts.getElementsByAttribute("value", aUrl).length > 0) {
return true;
}
return false;
},
/**
* Checks whether the script with the specified URL is selected in the list.
*
* @param string aUrl
* The script URL.
*/
isSelected: function DVS_isSelected(aUrl) {
if (this._scripts.selectedItem &&
this._scripts.selectedItem.value == aUrl) {
return true;
}
return false;
},
/**
* Selects the script with the specified URL from the list.
*
* @param string aUrl
* The script URL.
*/
selectScript: function DVS_selectScript(aUrl) {
for (let i = 0; i < this._scripts.itemCount; i++) {
if (this._scripts.getItemAtIndex(i).value == aUrl) {
this._scripts.selectedIndex = i;
break;
}
}
},
/** /**
* Adds a script to the scripts container. * Adds a script to the scripts container.
* If the script already exists (was previously added), null is returned. * If the script already exists (was previously added), null is returned.
@ -1086,7 +1127,7 @@ DebuggerView.Scripts = {
*/ */
addScript: function DVS_addScript(aUrl, aSource, aScriptNameText) { addScript: function DVS_addScript(aUrl, aSource, aScriptNameText) {
// make sure we don't duplicate anything // make sure we don't duplicate anything
if (this._scripts.getElementsByAttribute("value", aUrl).length > 0) { if (this.contains(aUrl)) {
return null; return null;
} }

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

@ -41,6 +41,8 @@
"use strict"; "use strict";
Components.utils.import("resource:///modules/source-editor.jsm");
var gInitialized = false; var gInitialized = false;
var gClient = null; var gClient = null;
var gTabClient = null; var gTabClient = null;
@ -255,11 +257,19 @@ var StackFrames = {
DebuggerView.Stackframes.highlightFrame(this.selectedFrame, true); DebuggerView.Stackframes.highlightFrame(this.selectedFrame, true);
} }
// Display the local variables.
let frame = this.activeThread.cachedFrames[aDepth]; let frame = this.activeThread.cachedFrames[aDepth];
if (!frame) { if (!frame) {
return; return;
} }
// Move the editor's caret to the proper line.
if (DebuggerView.Scripts.isSelected(frame.where.url) && frame.where.line) {
window.editor.setCaretPosition(frame.where.line - 1);
} else if (DebuggerView.Scripts.contains(frame.where.url)) {
DebuggerView.Scripts.selectScript(frame.where.url);
SourceScripts.onChange({ target: DebuggerView.Scripts._scripts });
window.editor.setCaretPosition(frame.where.line - 1);
}
// Display the local variables.
let localScope = DebuggerView.Properties.localScope; let localScope = DebuggerView.Properties.localScope;
localScope.empty(); localScope.empty();
// Add "this". // Add "this".
@ -435,9 +445,12 @@ var SourceScripts = {
}, },
/** /**
* Handler for the thread client's paused notification. * Handler for the thread client's paused notification. This is triggered only
* once, to retrieve the list of scripts known to the server from before the
* client was ready to handle new script notifications.
*/ */
onPaused: function SS_onPaused() { onPaused: function SS_onPaused() {
this.activeThread.removeListener("paused", this.onPaused);
this.activeThread.fillScripts(); this.activeThread.fillScripts();
}, },
@ -452,7 +465,6 @@ var SourceScripts = {
* Handler for the thread client's scriptsadded notification. * Handler for the thread client's scriptsadded notification.
*/ */
onScripts: function SS_onScripts() { onScripts: function SS_onScripts() {
this.onScriptsCleared();
for each (let script in this.activeThread.cachedScripts) { for each (let script in this.activeThread.cachedScripts) {
this._addScript(script); this._addScript(script);
} }
@ -468,12 +480,49 @@ var SourceScripts = {
/** /**
* Handler for changes on the selected source script. * Handler for changes on the selected source script.
*/ */
onChange: function SS_onClick(aEvent) { onChange: function SS_onChange(aEvent) {
let scripts = aEvent.target; let scripts = aEvent.target;
if (!scripts.selectedItem) {
return;
}
let script = scripts.selectedItem.getUserData("sourceScript"); let script = scripts.selectedItem.getUserData("sourceScript");
this.setEditorMode(script.url, script.contentType);
this._showScript(script); this._showScript(script);
}, },
/**
* Sets the proper editor mode (JS or HTML) according to the specified
* content type, or by determining the type from the URL.
*
* @param string aUrl
* The script URL.
* @param string aContentType [optional]
* The script content type.
*/
setEditorMode: function SS_setEditorMode(aUrl, aContentType) {
if (aContentType) {
if (/javascript/.test(aContentType)) {
window.editor.setMode(SourceEditor.MODES.JAVASCRIPT);
} else {
window.editor.setMode(SourceEditor.MODES.HTML);
}
return;
}
let url = aUrl;
// Trim the query part.
let q = url.indexOf('?');
if (q > -1) {
url = url.slice(0, q);
}
if (url.slice(-3) == ".js") {
window.editor.setMode(SourceEditor.MODES.JAVASCRIPT);
} else {
window.editor.setMode(SourceEditor.MODES.HTML);
}
},
/** /**
* Add the specified script to the list and display it in the editor if the * Add the specified script to the list and display it in the editor if the
* editor is empty. * editor is empty.

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

@ -70,6 +70,8 @@ _BROWSER_TEST_FILES = \
browser_dbg_location-changes.js \ browser_dbg_location-changes.js \
browser_dbg_script-switching.js \ browser_dbg_script-switching.js \
browser_dbg_pause-resume.js \ browser_dbg_pause-resume.js \
browser_dbg_update-editor-mode.js \
browser_dbg_select-line.js \
head.js \ head.js \
$(NULL) $(NULL)
@ -82,6 +84,8 @@ _BROWSER_TEST_PAGES = \
test-script-switching-01.js \ test-script-switching-01.js \
test-script-switching-02.js \ test-script-switching-02.js \
browser_dbg_frame-parameters.html \ browser_dbg_frame-parameters.html \
browser_dbg_update-editor-mode.html \
test-editor-mode \
$(NULL) $(NULL)
libs:: $(_BROWSER_TEST_FILES) libs:: $(_BROWSER_TEST_FILES)

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

@ -33,35 +33,24 @@ function test()
function testScriptsDisplay() { function testScriptsDisplay() {
gPane.activeThread.addOneTimeListener("scriptsadded", function() { gPane.activeThread.addOneTimeListener("scriptsadded", function() {
Services.tm.currentThread.dispatch({ run: function() { Services.tm.currentThread.dispatch({ run: function() {
let count = 0; gScripts = gDebugger.DebuggerView.Scripts._scripts;
is(gDebugger.StackFrames.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(gScripts.itemCount, 2, "Found the expected number of scripts.");
ok(gDebugger.editor.getText().search(/debugger/) != -1,
"The correct script was loaded initially.");
gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED, gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
function onScriptLoad() { function onChange() {
// Skip the first change event, since we're only interested in the
// second.
if (count++ < 1) {
return;
}
gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED, gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
onScriptLoad); onChange);
gScripts = gDebugger.DebuggerView.Scripts._scripts; testSwitchPaused();
is(gDebugger.StackFrames.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(gScripts.itemCount, 2, "Found the expected number of scripts.");
ok(gDebugger.editor.getText().search(/debugger/) != -1,
"The correct script was loaded initially.");
gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
function onChange() {
gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
onChange);
testSwitchPaused();
});
gScripts.selectedIndex = 0;
gDebugger.SourceScripts.onChange({ target: gScripts });
}); });
gScripts.selectedIndex = 0;
gDebugger.SourceScripts.onChange({ target: gScripts });
}}, 0); }}, 0);
}); });

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

@ -0,0 +1,81 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that selecting a stack frame loads the right script in the editor
* pane and highlights the proper line.
*/
const TAB_URL = "http://example.com/browser/browser/devtools/debugger/" +
"test/browser_dbg_script-switching.html";
let tempScope = {};
Cu.import("resource:///modules/source-editor.jsm", tempScope);
let SourceEditor = tempScope.SourceEditor;
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
var gScripts = null;
function test()
{
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.debuggerWindow;
testSelectLine();
});
}
function testSelectLine() {
gPane.activeThread.addOneTimeListener("scriptsadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
gScripts = gDebugger.DebuggerView.Scripts._scripts;
is(gDebugger.StackFrames.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(gScripts.itemCount, 2, "Found the expected number of scripts.");
ok(gDebugger.editor.getText().search(/debugger/) != -1,
"The correct script was loaded initially.");
// getCaretPosition is 0-based.
is(gDebugger.editor.getCaretPosition().line, 5,
"The correct line is selected.");
gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
function onChange() {
gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
onChange);
ok(gDebugger.editor.getText().search(/debugger/) == -1,
"The second script is no longer displayed.");
ok(gDebugger.editor.getText().search(/firstCall/) != -1,
"The first script is displayed.");
// Yield control back to the event loop so that the debugger has a
// chance to highlight the proper line.
executeSoon(function(){
// getCaretPosition is 0-based.
is(gDebugger.editor.getCaretPosition().line, 4,
"The correct line is selected.");
gDebugger.StackFrames.activeThread.resume(function() {
removeTab(gTab);
finish();
});
});
});
// Click the oldest stack frame.
let element = gDebugger.document.getElementById("stackframe-3");
EventUtils.synthesizeMouseAtCenter(element, {}, gDebugger);
}}, 0);
});
gDebuggee.firstCall();
}

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

@ -0,0 +1,12 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Browser Debugger Update Editor Mode Test</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script type="text/javascript" src="test-script-switching-01.js?q=a"></script>
<script type="text/javascript" src="test-editor-mode?a=b"></script>
</head>
<body>
</body>
</html>

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

@ -0,0 +1,78 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that updating the editor mode sets the right highlighting engine,
* and script URIs with extra query parameters also get the right engine.
*/
const TAB_URL = "http://example.com/browser/browser/devtools/debugger/" +
"test/browser_dbg_update-editor-mode.html";
let tempScope = {};
Cu.import("resource:///modules/source-editor.jsm", tempScope);
let SourceEditor = tempScope.SourceEditor;
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
var gScripts = null;
function test()
{
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.debuggerWindow;
testScriptsDisplay();
});
}
function testScriptsDisplay() {
gPane.activeThread.addOneTimeListener("scriptsadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
gScripts = gDebugger.DebuggerView.Scripts._scripts;
is(gDebugger.StackFrames.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(gScripts.itemCount, 2, "Found the expected number of scripts.");
is(gDebugger.editor.getMode(), SourceEditor.MODES.HTML,
"Found the expected editor mode.");
ok(gDebugger.editor.getText().search(/debugger/) != -1,
"The correct script was loaded initially.");
gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
function onChange() {
gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
onChange);
testSwitchPaused();
});
gScripts.selectedIndex = 0;
gDebugger.SourceScripts.onChange({ target: gScripts });
}}, 0);
});
gDebuggee.firstCall();
}
function testSwitchPaused()
{
ok(gDebugger.editor.getText().search(/debugger/) == -1,
"The second script is no longer displayed.");
ok(gDebugger.editor.getText().search(/firstCall/) != -1,
"The first script is displayed.");
is(gDebugger.editor.getMode(), SourceEditor.MODES.JAVASCRIPT,
"Found the expected editor mode.");
gDebugger.StackFrames.activeThread.resume(function() {
removeTab(gTab);
finish();
});
}

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

@ -0,0 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function secondCall() {
eval("debugger;");
}

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

@ -2,5 +2,6 @@
http://creativecommons.org/publicdomain/zero/1.0/ */ http://creativecommons.org/publicdomain/zero/1.0/ */
function secondCall() { function secondCall() {
// This comment is useful for browser_dbg_select-line.js.
eval("debugger;"); eval("debugger;");
} }

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

@ -246,7 +246,7 @@ Tilt.prototype = {
*/ */
update: function T_update(aNode) { update: function T_update(aNode) {
if (this.currentInstance) { if (this.currentInstance) {
this.currentInstance.presenter.highlightNode(aNode); this.currentInstance.presenter.highlightNode(aNode, "moveIntoView");
} }
}, },

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

@ -547,18 +547,6 @@ TiltUtils.getWindowId = function TU_getWindowId(aWindow)
.currentInnerWindowID; .currentInnerWindowID;
}; };
/**
* Gets the markup document viewer zoom for the currently selected browser.
*
* @param {Window} aChromeWindow
* the top-level browser window
*
* @return {Number} the zoom ammount
*/
TiltUtils.getDocumentZoom = function TU_getDocumentZoom(aChromeWindow) {
return aChromeWindow.gBrowser.selectedBrowser.markupDocumentViewer.fullZoom;
};
/** /**
* Sets the markup document viewer zoom for the currently selected browser. * Sets the markup document viewer zoom for the currently selected browser.
* *

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

@ -60,6 +60,7 @@ const WIREFRAME_COLOR = [0, 0, 0, 0.25];
const INTRO_TRANSITION_DURATION = 50; const INTRO_TRANSITION_DURATION = 50;
const OUTRO_TRANSITION_DURATION = 40; const OUTRO_TRANSITION_DURATION = 40;
const INITIAL_Z_TRANSLATION = 400; const INITIAL_Z_TRANSLATION = 400;
const MOVE_INTO_VIEW_ACCURACY = 50;
const MOUSE_CLICK_THRESHOLD = 10; const MOUSE_CLICK_THRESHOLD = 10;
const MOUSE_INTRO_DELAY = 10; const MOUSE_INTRO_DELAY = 10;
@ -250,7 +251,7 @@ TiltVisualizer.Presenter = function TV_Presenter(
* Modified by events in the controller through delegate functions. * Modified by events in the controller through delegate functions.
*/ */
this.transforms = { this.transforms = {
zoom: TiltUtils.getDocumentZoom(aChromeWindow), zoom: 1,
offset: vec3.create(), // mesh offset, aligned to the viewport center offset: vec3.create(), // mesh offset, aligned to the viewport center
translation: vec3.create(), // scene translation, on the [x, y, z] axis translation: vec3.create(), // scene translation, on the [x, y, z] axis
rotation: quat4.create() // scene rotation, expressed as a quaternion rotation: quat4.create() // scene rotation, expressed as a quaternion
@ -280,6 +281,7 @@ TiltVisualizer.Presenter = function TV_Presenter(
let setup = function TVP_setup() let setup = function TVP_setup()
{ {
let renderer = this.renderer; let renderer = this.renderer;
let inspector = this.chromeWindow.InspectorUI;
// if the renderer was destroyed, don't continue setup // if the renderer was destroyed, don't continue setup
if (!renderer || !renderer.context) { if (!renderer || !renderer.context) {
@ -294,6 +296,11 @@ TiltVisualizer.Presenter = function TV_Presenter(
uniforms: ["mvMatrix", "projMatrix", "sampler"] uniforms: ["mvMatrix", "projMatrix", "sampler"]
}); });
// get the document zoom to properly scale the visualization
if (inspector.highlighter) {
this.transforms.zoom = inspector.highlighter.zoom;
}
this.setupTexture(); this.setupTexture();
this.setupMeshData(); this.setupMeshData();
this.setupEventListeners(); this.setupEventListeners();
@ -546,9 +553,8 @@ TiltVisualizer.Presenter.prototype = {
if (!this._initialMeshConfiguration) { if (!this._initialMeshConfiguration) {
this._initialMeshConfiguration = true; this._initialMeshConfiguration = true;
let zoom = this.transforms.zoom; let width = renderer.width;
let width = Math.min(aData.meshWidth * zoom, renderer.width); let height = renderer.height;
let height = Math.min(aData.meshHeight * zoom, renderer.height);
// set the necessary mesh offsets // set the necessary mesh offsets
this.transforms.offset[0] = -width * 0.5; this.transforms.offset[0] = -width * 0.5;
@ -620,7 +626,7 @@ TiltVisualizer.Presenter.prototype = {
*/ */
onResize: function TVP_onResize(e) onResize: function TVP_onResize(e)
{ {
let zoom = TiltUtils.getDocumentZoom(this.chromeWindow); let zoom = this.chromeWindow.InspectorUI.highlighter.zoom;
let width = e.target.innerWidth * zoom; let width = e.target.innerWidth * zoom;
let height = e.target.innerHeight * zoom; let height = e.target.innerHeight * zoom;
@ -636,10 +642,12 @@ TiltVisualizer.Presenter.prototype = {
* *
* @param {Element} aNode * @param {Element} aNode
* the html node to be highlighted * the html node to be highlighted
* @param {String} aFlags
* flags specifying highlighting options
*/ */
highlightNode: function TVP_highlightNode(aNode) highlightNode: function TVP_highlightNode(aNode, aFlags)
{ {
this.highlightNodeFor(this.traverseData.nodes.indexOf(aNode)); this.highlightNodeFor(this.traverseData.nodes.indexOf(aNode), aFlags);
}, },
/** /**
@ -698,8 +706,10 @@ TiltVisualizer.Presenter.prototype = {
* *
* @param {Number} aNodeIndex * @param {Number} aNodeIndex
* the index of the node in the this.traverseData array * the index of the node in the this.traverseData array
* @param {String} aFlags
* flags specifying highlighting options
*/ */
highlightNodeFor: function TVP_highlightNodeFor(aNodeIndex) highlightNodeFor: function TVP_highlightNodeFor(aNodeIndex, aFlags)
{ {
this.redraw = true; this.redraw = true;
@ -744,6 +754,17 @@ TiltVisualizer.Presenter.prototype = {
this.contentWindow.innerHeight < y || this.contentWindow.innerHeight < y ||
this.contentWindow.pageYOffset > 0); this.contentWindow.pageYOffset > 0);
// if something is highlighted, make sure it's inside the current viewport;
// the point which should be moved into view is considered the center [x, y]
// position along the top edge of the currently selected node
if (aFlags && aFlags.indexOf("moveIntoView") !== -1)
{
this.controller.arcball.moveIntoView(vec3.lerp(
vec3.scale(this.highlight.v0, this.transforms.zoom, []),
vec3.scale(this.highlight.v1, this.transforms.zoom, []), 0.5));
}
Services.obs.notifyObservers(null, this.NOTIFICATIONS.HIGHLIGHTING, null); Services.obs.notifyObservers(null, this.NOTIFICATIONS.HIGHLIGHTING, null);
}, },
@ -813,7 +834,7 @@ TiltVisualizer.Presenter.prototype = {
} }
}, false); }, false);
let zoom = TiltUtils.getDocumentZoom(this.chromeWindow); let zoom = this.chromeWindow.InspectorUI.highlighter.zoom;
let width = this.renderer.width * zoom; let width = this.renderer.width * zoom;
let height = this.renderer.height * zoom; let height = this.renderer.height * zoom;
let mesh = this.meshStacks; let mesh = this.meshStacks;
@ -997,6 +1018,7 @@ TiltVisualizer.Controller = function TV_Controller(aCanvas, aPresenter)
* Save a reference to the presenter to modify its model-view transforms. * Save a reference to the presenter to modify its model-view transforms.
*/ */
this.presenter = aPresenter; this.presenter = aPresenter;
this.presenter.controller = this;
/** /**
* The initial controller dimensions and offset, in pixels. * The initial controller dimensions and offset, in pixels.
@ -1256,7 +1278,7 @@ TiltVisualizer.Controller.prototype = {
*/ */
onResize: function TVC_onResize(e) onResize: function TVC_onResize(e)
{ {
let zoom = TiltUtils.getDocumentZoom(this.presenter.chromeWindow); let zoom = this.presenter.chromeWindow.InspectorUI.highlighter.zoom;
let width = e.target.innerWidth * zoom; let width = e.target.innerWidth * zoom;
let height = e.target.innerHeight * zoom; let height = e.target.innerHeight * zoom;
@ -1728,6 +1750,25 @@ TiltVisualizer.Arcball.prototype = {
this._mouseButton = -1; this._mouseButton = -1;
}, },
/**
* Moves a target point into view only if it's outside the currently visible
* area bounds (in which case it also resets any additional transforms).
*
* @param {Arary} aPoint
* the [x, y] point which should be brought into view
*/
moveIntoView: function TVA_moveIntoView(aPoint) {
let visiblePointX = -(this._currentTrans[0] + this._additionalTrans[0]);
let visiblePointY = -(this._currentTrans[1] + this._additionalTrans[1]);
if (aPoint[1] - visiblePointY - MOVE_INTO_VIEW_ACCURACY > this.height ||
aPoint[1] - visiblePointY + MOVE_INTO_VIEW_ACCURACY < 0 ||
aPoint[0] - visiblePointX > this.width ||
aPoint[0] - visiblePointX < 0) {
this.reset([0, -aPoint[1]]);
}
},
/** /**
* Resize this implementation to use different bounds. * Resize this implementation to use different bounds.
* This function is automatically called when the arcball is created. * This function is automatically called when the arcball is created.

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

@ -76,6 +76,7 @@ _BROWSER_TEST_FILES = \
browser_tilt_math07.js \ browser_tilt_math07.js \
browser_tilt_picking.js \ browser_tilt_picking.js \
browser_tilt_picking_delete.js \ browser_tilt_picking_delete.js \
browser_tilt_picking_highlight01-offs.js \
browser_tilt_picking_highlight01.js \ browser_tilt_picking_highlight01.js \
browser_tilt_picking_highlight02.js \ browser_tilt_picking_highlight02.js \
browser_tilt_picking_highlight03.js \ browser_tilt_picking_highlight03.js \

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

@ -23,7 +23,7 @@ function test() {
presenter.onSetupMesh = function() { presenter.onSetupMesh = function() {
presenter.pickNode(canvas.width / 2, canvas.height / 2, { presenter.pickNode(canvas.width / 2, 10, {
onpick: function(data) onpick: function(data)
{ {
ok(data.index > 0, ok(data.index > 0,

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

@ -24,8 +24,7 @@ function test() {
Services.obs.addObserver(whenNodeRemoved, NODE_REMOVED, false); Services.obs.addObserver(whenNodeRemoved, NODE_REMOVED, false);
presenter.onSetupMesh = function() { presenter.onSetupMesh = function() {
presenter.highlightNodeAt(presenter.canvas.width / 2, presenter.highlightNodeAt(presenter.canvas.width / 2, 10, {
presenter.canvas.height / 2, {
onpick: function() onpick: function()
{ {
ok(presenter._currentSelection > 0, ok(presenter._currentSelection > 0,

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

@ -0,0 +1,70 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
let presenter;
function test() {
if (!isTiltEnabled()) {
info("Skipping highlight test because Tilt isn't enabled.");
return;
}
if (!isWebGLSupported()) {
info("Skipping highlight test because WebGL isn't supported.");
return;
}
requestLongerTimeout(10);
waitForExplicitFinish();
createTab(function() {
createTilt({
onTiltOpen: function(instance)
{
presenter = instance.presenter;
Services.obs.addObserver(whenHighlighting, HIGHLIGHTING, false);
presenter.onInitializationFinished = function() {
let contentDocument = presenter.contentWindow.document;
let div = contentDocument.getElementById("far-far-away");
presenter.highlightNode(div, "moveIntoView");
};
}
});
});
}
function whenHighlighting() {
ok(presenter._currentSelection > 0,
"Highlighting a node didn't work properly.");
ok(!presenter.highlight.disabled,
"After highlighting a node, it should be highlighted. D'oh.");
ok(presenter.controller.arcball._resetInterval,
"Highlighting a node that's not already visible should trigger a reset!");
executeSoon(function() {
Services.obs.addObserver(whenUnhighlighting, UNHIGHLIGHTING, false);
presenter.highlightNode(null);
});
}
function whenUnhighlighting() {
ok(presenter._currentSelection < 0,
"Unhighlighting a should remove the current selection.");
ok(presenter.highlight.disabled,
"After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
executeSoon(function() {
Services.obs.addObserver(cleanup, DESTROYED, false);
InspectorUI.closeInspectorUI();
});
}
function cleanup() {
Services.obs.removeObserver(whenHighlighting, HIGHLIGHTING);
Services.obs.removeObserver(whenUnhighlighting, UNHIGHLIGHTING);
Services.obs.removeObserver(cleanup, DESTROYED);
gBrowser.removeCurrentTab();
finish();
}

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

@ -27,7 +27,7 @@ function test() {
let contentDocument = presenter.contentWindow.document; let contentDocument = presenter.contentWindow.document;
let div = contentDocument.getElementById("first-law"); let div = contentDocument.getElementById("first-law");
presenter.highlightNode(div); presenter.highlightNode(div, "moveIntoView");
}; };
} }
}); });
@ -39,6 +39,8 @@ function whenHighlighting() {
"Highlighting a node didn't work properly."); "Highlighting a node didn't work properly.");
ok(!presenter.highlight.disabled, ok(!presenter.highlight.disabled,
"After highlighting a node, it should be highlighted. D'oh."); "After highlighting a node, it should be highlighted. D'oh.");
ok(!presenter.controller.arcball._resetInterval,
"Highlighting a node that's already visible shouldn't trigger a reset.");
executeSoon(function() { executeSoon(function() {
Services.obs.addObserver(whenUnhighlighting, UNHIGHLIGHTING, false); Services.obs.addObserver(whenUnhighlighting, UNHIGHLIGHTING, false);

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

@ -24,8 +24,7 @@ function test() {
Services.obs.addObserver(whenHighlighting, HIGHLIGHTING, false); Services.obs.addObserver(whenHighlighting, HIGHLIGHTING, false);
presenter.onSetupMesh = function() { presenter.onSetupMesh = function() {
presenter.highlightNodeAt(presenter.canvas.width / 2, presenter.highlightNodeAt(presenter.canvas.width / 2, 10);
presenter.canvas.height / 2);
}; };
} }
}); });

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

@ -6,13 +6,6 @@ const ZOOM = 2;
const RESIZE = 50; const RESIZE = 50;
function test() { function test() {
let random = Math.random() * 10;
TiltUtils.setDocumentZoom(window, random);
ok(isApprox(TiltUtils.getDocumentZoom(window), random),
"The getDocumentZoom utility function didn't return the expected results.");
if (!isTiltEnabled()) { if (!isTiltEnabled()) {
info("Skipping controller test because Tilt isn't enabled."); info("Skipping controller test because Tilt isn't enabled.");
return; return;
@ -32,6 +25,9 @@ function test() {
}, },
onTiltOpen: function(instance) onTiltOpen: function(instance)
{ {
ok(isApprox(InspectorUI.highlighter.zoom, ZOOM),
"The Highlighter zoom doesn't have the expected results.");
ok(isApprox(instance.presenter.transforms.zoom, ZOOM), ok(isApprox(instance.presenter.transforms.zoom, ZOOM),
"The presenter transforms zoom wasn't initially set correctly."); "The presenter transforms zoom wasn't initially set correctly.");
@ -74,10 +70,11 @@ function test() {
window.resizeBy(RESIZE * ZOOM, RESIZE * ZOOM); window.resizeBy(RESIZE * ZOOM, RESIZE * ZOOM);
Services.obs.addObserver(cleanup, DESTROYED, false); Services.obs.addObserver(cleanup, DESTROYED, false);
InspectorUI.closeInspectorUI(); InspectorUI.closeInspectorUI();
}); });
}, }
}); });
}); });
} }

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

@ -37,6 +37,9 @@ const DEFAULT_HTML = "data:text/html," +
"A robot must protect its own existence as long as such protection " + "A robot must protect its own existence as long as such protection " +
"does not conflict with the First or Second Laws." + "does not conflict with the First or Second Laws." +
"</div>" + "</div>" +
"<div id='far-far-away' style='position: absolute; top: 250%;'>" +
"I like bacon." +
"</div>" +
"<body>" + "<body>" +
"</html>"; "</html>";
@ -137,8 +140,10 @@ function createTilt(callbacks, close) {
if ("function" === typeof callbacks.onInspectorOpen) { if ("function" === typeof callbacks.onInspectorOpen) {
callbacks.onInspectorOpen(); callbacks.onInspectorOpen();
} }
Services.obs.addObserver(onTiltOpen, INITIALIZING, false); executeSoon(function() {
Tilt.initialize(); Services.obs.addObserver(onTiltOpen, INITIALIZING, false);
Tilt.initialize();
});
}); });
} }
@ -150,8 +155,10 @@ function createTilt(callbacks, close) {
callbacks.onTiltOpen(Tilt.visualizers[Tilt.currentWindowId]); callbacks.onTiltOpen(Tilt.visualizers[Tilt.currentWindowId]);
} }
if (close) { if (close) {
Services.obs.addObserver(onTiltClose, DESTROYED, false); executeSoon(function() {
Tilt.destroy(Tilt.currentWindowId); Services.obs.addObserver(onTiltClose, DESTROYED, false);
Tilt.destroy(Tilt.currentWindowId);
});
} }
}); });
} }
@ -164,8 +171,10 @@ function createTilt(callbacks, close) {
callbacks.onTiltClose(); callbacks.onTiltClose();
} }
if (close) { if (close) {
Services.obs.addObserver(onInspectorClose, INSPECTOR_CLOSED, false); executeSoon(function() {
InspectorUI.closeInspectorUI(); Services.obs.addObserver(onInspectorClose, INSPECTOR_CLOSED, false);
InspectorUI.closeInspectorUI();
});
} }
}); });
} }

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

@ -1095,6 +1095,10 @@ FrameActor.prototype = {
grip.environment = envActor ? envActor.grip() : envActor; grip.environment = envActor ? envActor.grip() : envActor;
grip["this"] = this.threadActor.createValueGrip(this.frame["this"]); grip["this"] = this.threadActor.createValueGrip(this.frame["this"]);
grip.arguments = this._args(); grip.arguments = this._args();
if (this.frame.script) {
grip.where = { url: this.frame.script.url,
line: this.frame.script.getOffsetLine(this.frame.offset) };
}
if (!this.frame.older) { if (!this.frame.older) {
grip.oldest = true; grip.oldest = true;