bug 808369 - Use VariablesView in the Scratchpad; r=msucan

This commit is contained in:
Brandon Benvie 2013-05-06 19:11:44 -04:00
Родитель 2307ce5a06
Коммит 744abbee16
10 изменённых файлов: 221 добавлений и 89 удалений

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

@ -30,6 +30,12 @@ Cu.import("resource:///modules/devtools/gDevTools.jsm");
Cu.import("resource://gre/modules/osfile.jsm");
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
XPCOMUtils.defineLazyModuleGetter(this, "VariablesView",
"resource:///modules/devtools/VariablesView.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "devtools",
"resource:///modules/devtools/gDevTools.jsm");
const SCRATCHPAD_CONTEXT_CONTENT = 1;
const SCRATCHPAD_CONTEXT_BROWSER = 2;
const SCRATCHPAD_L10N = "chrome://browser/locale/devtools/scratchpad.properties";
@ -38,7 +44,9 @@ const PREF_RECENT_FILES_MAX = "devtools.scratchpad.recentFilesMax";
const BUTTON_POSITION_SAVE = 0;
const BUTTON_POSITION_CANCEL = 1;
const BUTTON_POSITION_DONT_SAVE = 2;
const BUTTON_POSITION_REVERT=0;
const BUTTON_POSITION_REVERT = 0;
const VARIABLES_VIEW_URL = "chrome://browser/content/devtools/widgets/VariablesView.xul";
/**
* The scratchpad object handles the Scratchpad window functionality.
@ -253,6 +261,18 @@ var Scratchpad = {
return "Scratchpad/" + this._instanceId;
},
/**
* Sidebar that contains the VariablesView for object inspection.
*/
get sidebar()
{
if (!this._sidebar) {
this._sidebar = new ScratchpadSidebar();
}
return this._sidebar;
},
/**
* Get the Cu.Sandbox object for the active tab content window object. Note
* that the returned object is cached for later reuse. The cached object is
@ -423,25 +443,35 @@ var Scratchpad = {
/**
* Execute the selected text (if any) or the entire editor content in the
* current context. The resulting object is opened up in the Property Panel
* for inspection.
* current context. If the result is primitive then it is written as a
* comment. Otherwise, the resulting object is inspected up in the sidebar.
*
* @return Promise
* The promise for the script evaluation result.
*/
inspect: function SP_inspect()
{
let promise = this.execute();
promise.then(([aString, aError, aResult]) => {
let deferred = Promise.defer();
let reject = aReason => deferred.reject(aReason);
this.execute().then(([aString, aError, aResult]) => {
let resolve = () => deferred.resolve([aString, aError, aResult]);
if (aError) {
this.writeAsErrorComment(aError);
resolve();
}
else if (!isObject(aResult)) {
this.writeAsComment(aResult);
resolve();
}
else {
this.deselect();
this.openPropertyPanel(aString, aResult);
this.sidebar.open(aString, aResult).then(resolve, reject);
}
});
return promise;
}, reject);
return deferred.promise;
},
/**
@ -552,58 +582,6 @@ var Scratchpad = {
this.writeAsComment(newComment);
},
/**
* Open the Property Panel to inspect the given object.
*
* @param string aEvalString
* The string that was evaluated. This is re-used when the user updates
* the properties list, by clicking the Update button.
* @param object aOutputObject
* The object to inspect, which is the aEvalString evaluation result.
* @return object
* The PropertyPanel object instance.
*/
openPropertyPanel: function SP_openPropertyPanel(aEvalString, aOutputObject)
{
let propPanel;
// The property panel has a button:
// `Update`: reexecutes the string executed on the command line. The
// result will be inspected by this panel.
let buttons = [];
// If there is a evalString passed to this function, then add a `Update`
// button to the panel so that the evalString can be reexecuted to update
// the content of the panel.
if (aEvalString !== null) {
buttons.push({
label: this.strings.
GetStringFromName("propertyPanel.updateButton.label"),
accesskey: this.strings.
GetStringFromName("propertyPanel.updateButton.accesskey"),
oncommand: () => {
this.evalForContext(aEvalString).then(([, aError, aResult]) => {
if (!aError) {
propPanel.treeView.data = { object: aResult };
}
});
}
});
}
let doc = this.browserWindow.document;
let parent = doc.getElementById("mainPopupSet");
let title = String(aOutputObject);
propPanel = new PropertyPanel(parent, title, { object: aOutputObject },
buttons);
let panel = propPanel.panel;
panel.setAttribute("class", "scratchpad_propertyPanel");
panel.openPopup(null, "after_pointer", 0, 0, false, false);
panel.sizeTo(200, 400);
return propPanel;
},
// Menu Operations
/**
@ -1495,6 +1473,132 @@ var Scratchpad = {
},
};
/**
* Encapsulates management of the sidebar containing the VariablesView for
* object inspection.
*/
function ScratchpadSidebar()
{
let ToolSidebar = devtools.require("devtools/framework/sidebar").ToolSidebar;
let tabbox = document.querySelector("#scratchpad-sidebar");
this._sidebar = new ToolSidebar(tabbox, this);
this._splitter = document.querySelector(".devtools-side-splitter");
}
ScratchpadSidebar.prototype = {
/*
* The ToolSidebar for this sidebar.
*/
_sidebar: null,
/*
* The splitter element between the sidebar and the editor.
*/
_splitter: null,
/*
* The VariablesView for this sidebar.
*/
variablesView: null,
/*
* Whether the sidebar is currently shown.
*/
visible: false,
/**
* Open the sidebar, if not open already, and populate it with the properties
* of the given object.
*
* @param string aString
* The string that was evaluated.
* @param object aObject
* The object to inspect, which is the aEvalString evaluation result.
* @return Promise
* A promise that will resolve once the sidebar is open.
*/
open: function SS_open(aEvalString, aObject)
{
this.show();
let deferred = Promise.defer();
let onTabReady = () => {
if (!this.variablesView) {
let window = this._sidebar.getWindowForTab("variablesview");
let container = window.document.querySelector("#variables");
this.variablesView = new VariablesView(container);
}
this._update(aObject).then(() => deferred.resolve());
};
if (this._sidebar.getCurrentTabID() == "variablesview") {
onTabReady();
}
else {
this._sidebar.once("variablesview-ready", onTabReady);
this._sidebar.addTab("variablesview", VARIABLES_VIEW_URL, true);
}
return deferred.promise;
},
/**
* Show the sidebar.
*/
show: function SS_show()
{
if (!this.visible) {
this.visible = true;
this._sidebar.show();
this._splitter.setAttribute("state", "open");
}
},
/**
* Hide the sidebar.
*/
hide: function SS_hide()
{
if (this.visible) {
this.visible = false;
this._sidebar.hide();
this._splitter.setAttribute("state", "collapsed");
}
},
/**
* Update the object currently inspected by the sidebar.
*
* @param object aObject
* The object to inspect in the sidebar.
* @return Promise
* A promise that resolves when the update completes.
*/
_update: function SS__update(aObject)
{
let deferred = Promise.defer();
this.variablesView.rawObject = aObject;
// In the future this will work on remote values (bug 825039).
setTimeout(() => deferred.resolve(), 0);
return deferred.promise;
}
};
/**
* Check whether a value is non-primitive.
*/
function isObject(aValue)
{
let type = typeof aValue;
return type == "object" ? aValue != null : type == "function";
}
/**
* The PreferenceObserver listens for preference changes while Scratchpad is
* running.

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

@ -8,7 +8,9 @@
<!ENTITY % scratchpadDTD SYSTEM "chrome://browser/locale/devtools/scratchpad.dtd" >
%scratchpadDTD;
]>
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
<?xml-stylesheet href="chrome://global/skin/global.css"?>
<?xml-stylesheet href="chrome://browser/skin/devtools/common.css"?>
<?xml-stylesheet href="chrome://browser/skin/devtools/scratchpad.css"?>
<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
<?xul-overlay href="chrome://browser/content/source-editor-overlay.xul"?>
@ -280,7 +282,16 @@
</popupset>
<notificationbox id="scratchpad-notificationbox" flex="1">
<hbox id="scratchpad-editor" flex="1"/>
<hbox flex="1">
<vbox id="scratchpad-editor" flex="1"/>
<splitter class="devtools-side-splitter"
collapse="after"
state="collapsed"/>
<tabbox id="scratchpad-sidebar" class="devtools-sidebar-tabs" width="300">
<tabs/>
<tabpanels flex="1"/>
</tabbox>
</hbox>
</notificationbox>
</window>

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

@ -12,47 +12,35 @@ function test()
openScratchpad(runTests);
}, true);
content.location = "data:text/html,<title>foobarBug636725</title>" +
"<p>test inspect() in Scratchpad";
content.location = "data:text/html;charset=utf8,<p>test inspect() in Scratchpad</p>";
}
function runTests()
{
let sp = gScratchpadWindow.Scratchpad;
sp.setText("document");
sp.setText("({ a: 'foobarBug636725' })");
sp.inspect().then(function() {
let sidebar = sp.sidebar;
ok(sidebar.visible, "sidebar is open");
let propPanel = document.querySelector(".scratchpad_propertyPanel");
ok(propPanel, "property panel is open");
propPanel.addEventListener("popupshown", function onPopupShown() {
propPanel.removeEventListener("popupshown", onPopupShown, false);
let found = false;
let tree = propPanel.querySelector("tree");
ok(tree, "property panel tree found");
let column = tree.columns[0];
let found = false;
for (let i = 0; i < tree.view.rowCount; i++) {
let cell = tree.view.getCellText(i, column);
if (cell == 'title: "foobarBug636725"') {
found = true;
break;
outer: for (let scope in sidebar.variablesView) {
for (let [, obj] in scope) {
for (let [, prop] in obj) {
if (prop.name == "a" && prop.value == "foobarBug636725") {
found = true;
break outer;
}
}
}
ok(found, "found the document.title property");
}
executeSoon(function() {
propPanel.hidePopup();
ok(found, "found the property");
finish();
});
}, false);
}, function() {
notok(true, "document not found");
finish();
});
}
}

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

@ -0,0 +1,5 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
%include ../../shared/devtools/scratchpad.inc.css

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

@ -171,6 +171,7 @@ browser.jar:
skin/classic/browser/devtools/debugger.css (devtools/debugger.css)
* skin/classic/browser/devtools/profiler.css (devtools/profiler.css)
skin/classic/browser/devtools/netmonitor.css (devtools/netmonitor.css)
* skin/classic/browser/devtools/scratchpad.css (devtools/scratchpad.css)
skin/classic/browser/devtools/magnifying-glass.png (devtools/magnifying-glass.png)
skin/classic/browser/devtools/option-icon.png (devtools/option-icon.png)
skin/classic/browser/devtools/itemToggle.png (devtools/itemToggle.png)

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

@ -0,0 +1,5 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
%include ../../shared/devtools/scratchpad.inc.css

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

@ -262,6 +262,7 @@ browser.jar:
* skin/classic/browser/devtools/debugger.css (devtools/debugger.css)
* skin/classic/browser/devtools/profiler.css (devtools/profiler.css)
skin/classic/browser/devtools/netmonitor.css (devtools/netmonitor.css)
* skin/classic/browser/devtools/scratchpad.css (devtools/scratchpad.css)
skin/classic/browser/devtools/magnifying-glass.png (devtools/magnifying-glass.png)
skin/classic/browser/devtools/option-icon.png (devtools/option-icon.png)
skin/classic/browser/devtools/itemToggle.png (devtools/itemToggle.png)

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

@ -0,0 +1,10 @@
%if 0
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
%endif
#scratchpad-sidebar > tabs {
height: 0;
border: none;
}

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

@ -0,0 +1,5 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
%include ../../shared/devtools/scratchpad.inc.css

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

@ -199,6 +199,7 @@ browser.jar:
skin/classic/browser/devtools/debugger.css (devtools/debugger.css)
* skin/classic/browser/devtools/profiler.css (devtools/profiler.css)
skin/classic/browser/devtools/netmonitor.css (devtools/netmonitor.css)
* skin/classic/browser/devtools/scratchpad.css (devtools/scratchpad.css)
skin/classic/browser/devtools/magnifying-glass.png (devtools/magnifying-glass.png)
skin/classic/browser/devtools/option-icon.png (devtools/option-icon.png)
skin/classic/browser/devtools/itemToggle.png (devtools/itemToggle.png)
@ -446,6 +447,7 @@ browser.jar:
skin/classic/aero/browser/devtools/debugger.css (devtools/debugger.css)
* skin/classic/aero/browser/devtools/profiler.css (devtools/profiler.css)
skin/classic/aero/browser/devtools/netmonitor.css (devtools/netmonitor.css)
* skin/classic/aero/browser/devtools/scratchpad.css (devtools/scratchpad.css)
skin/classic/aero/browser/devtools/magnifying-glass.png (devtools/magnifying-glass.png)
skin/classic/aero/browser/devtools/option-icon.png (devtools/option-icon.png)
skin/classic/aero/browser/devtools/itemToggle.png (devtools/itemToggle.png)