2013-08-01 01:53:31 -07:00
|
|
|
/* -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2012-11-30 00:07:59 -08:00
|
|
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
|
|
|
/* 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/. */
|
|
|
|
|
2013-06-13 16:41:00 -07:00
|
|
|
const {Cu} = require("chrome");
|
|
|
|
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
|
|
|
2013-07-11 00:12:20 -07:00
|
|
|
var promise = require("sdk/core/promise");
|
2013-04-11 13:59:08 -07:00
|
|
|
var EventEmitter = require("devtools/shared/event-emitter");
|
2013-05-24 03:26:17 -07:00
|
|
|
var Telemetry = require("devtools/shared/telemetry");
|
2012-11-30 00:07:59 -08:00
|
|
|
|
|
|
|
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ToolSidebar provides methods to register tabs in the sidebar.
|
|
|
|
* It's assumed that the sidebar contains a xul:tabbox.
|
|
|
|
*
|
|
|
|
* @param {Node} tabbox
|
|
|
|
* <tabbox> node;
|
|
|
|
* @param {ToolPanel} panel
|
|
|
|
* Related ToolPanel instance;
|
2013-06-13 16:41:00 -07:00
|
|
|
* @param {String} uid
|
|
|
|
* Unique ID
|
2012-11-30 00:07:59 -08:00
|
|
|
* @param {Boolean} showTabstripe
|
|
|
|
* Show the tabs.
|
|
|
|
*/
|
2013-06-13 16:41:00 -07:00
|
|
|
function ToolSidebar(tabbox, panel, uid, showTabstripe=true)
|
2012-11-30 00:07:59 -08:00
|
|
|
{
|
2012-12-13 23:05:00 -08:00
|
|
|
EventEmitter.decorate(this);
|
2012-11-30 00:07:59 -08:00
|
|
|
|
|
|
|
this._tabbox = tabbox;
|
2013-06-13 16:41:00 -07:00
|
|
|
this._uid = uid;
|
2012-11-30 00:07:59 -08:00
|
|
|
this._panelDoc = this._tabbox.ownerDocument;
|
|
|
|
this._toolPanel = panel;
|
|
|
|
|
2013-06-13 16:41:00 -07:00
|
|
|
try {
|
|
|
|
this._width = Services.prefs.getIntPref("devtools.toolsidebar-width." + this._uid);
|
|
|
|
} catch(e) {}
|
|
|
|
|
2013-05-24 03:26:17 -07:00
|
|
|
this._telemetry = new Telemetry();
|
|
|
|
|
2012-11-30 00:07:59 -08:00
|
|
|
this._tabbox.tabpanels.addEventListener("select", this, true);
|
|
|
|
|
|
|
|
this._tabs = new Map();
|
|
|
|
|
|
|
|
if (!showTabstripe) {
|
|
|
|
this._tabbox.setAttribute("hidetabs", "true");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-11 13:59:08 -07:00
|
|
|
exports.ToolSidebar = ToolSidebar;
|
|
|
|
|
2012-11-30 00:07:59 -08:00
|
|
|
ToolSidebar.prototype = {
|
|
|
|
/**
|
|
|
|
* Register a tab. A tab is a document.
|
|
|
|
* The document must have a title, which will be used as the name of the tab.
|
|
|
|
*
|
|
|
|
* @param {string} tab uniq id
|
|
|
|
* @param {string} url
|
|
|
|
*/
|
|
|
|
addTab: function ToolSidebar_addTab(id, url, selected=false) {
|
|
|
|
let iframe = this._panelDoc.createElementNS(XULNS, "iframe");
|
|
|
|
iframe.className = "iframe-" + id;
|
|
|
|
iframe.setAttribute("flex", "1");
|
|
|
|
iframe.setAttribute("src", url);
|
2013-03-21 05:58:07 -07:00
|
|
|
iframe.tooltip = "aHTMLTooltip";
|
2012-11-30 00:07:59 -08:00
|
|
|
|
|
|
|
let tab = this._tabbox.tabs.appendItem();
|
2013-01-08 16:15:00 -08:00
|
|
|
tab.setAttribute("label", ""); // Avoid showing "undefined" while the tab is loading
|
2012-11-30 00:07:59 -08:00
|
|
|
|
|
|
|
let onIFrameLoaded = function() {
|
|
|
|
tab.setAttribute("label", iframe.contentDocument.title);
|
2013-04-09 02:46:30 -07:00
|
|
|
iframe.removeEventListener("load", onIFrameLoaded, true);
|
2012-11-30 00:07:59 -08:00
|
|
|
if ("setPanel" in iframe.contentWindow) {
|
|
|
|
iframe.contentWindow.setPanel(this._toolPanel, iframe);
|
|
|
|
}
|
|
|
|
this.emit(id + "-ready");
|
|
|
|
}.bind(this);
|
|
|
|
|
2013-04-09 02:46:30 -07:00
|
|
|
iframe.addEventListener("load", onIFrameLoaded, true);
|
2012-11-30 00:07:59 -08:00
|
|
|
|
|
|
|
let tabpanel = this._panelDoc.createElementNS(XULNS, "tabpanel");
|
|
|
|
tabpanel.setAttribute("id", "sidebar-panel-" + id);
|
|
|
|
tabpanel.appendChild(iframe);
|
|
|
|
this._tabbox.tabpanels.appendChild(tabpanel);
|
|
|
|
|
2013-03-21 05:58:07 -07:00
|
|
|
this._tooltip = this._panelDoc.createElementNS(XULNS, "tooltip");
|
|
|
|
this._tooltip.id = "aHTMLTooltip";
|
|
|
|
tabpanel.appendChild(this._tooltip);
|
|
|
|
this._tooltip.page = true;
|
|
|
|
|
2012-11-30 00:07:59 -08:00
|
|
|
tab.linkedPanel = "sidebar-panel-" + id;
|
|
|
|
|
|
|
|
// We store the index of this tab.
|
|
|
|
this._tabs.set(id, tab);
|
|
|
|
|
|
|
|
if (selected) {
|
|
|
|
// For some reason I don't understand, if we call this.select in this
|
|
|
|
// event loop (after inserting the tab), the tab will never get the
|
|
|
|
// the "selected" attribute set to true.
|
|
|
|
this._panelDoc.defaultView.setTimeout(function() {
|
|
|
|
this.select(id);
|
2013-04-09 02:46:30 -07:00
|
|
|
}.bind(this), 10);
|
2012-11-30 00:07:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
this.emit("new-tab-registered", id);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Select a specific tab.
|
|
|
|
*/
|
|
|
|
select: function ToolSidebar_select(id) {
|
|
|
|
let tab = this._tabs.get(id);
|
|
|
|
if (tab) {
|
|
|
|
this._tabbox.selectedTab = tab;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the id of the selected tab.
|
|
|
|
*/
|
|
|
|
getCurrentTabID: function ToolSidebar_getCurrentTabID() {
|
|
|
|
let currentID = null;
|
|
|
|
for (let [id, tab] of this._tabs) {
|
|
|
|
if (this._tabbox.tabs.selectedItem == tab) {
|
|
|
|
currentID = id;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return currentID;
|
|
|
|
},
|
|
|
|
|
2012-12-17 11:29:08 -08:00
|
|
|
/**
|
|
|
|
* Returns the requested tab based on the id.
|
|
|
|
*
|
|
|
|
* @param String id
|
|
|
|
* unique id of the requested tab.
|
|
|
|
*/
|
|
|
|
getTab: function ToolSidebar_getTab(id) {
|
|
|
|
return this._tabbox.tabpanels.querySelector("#sidebar-panel-" + id);
|
|
|
|
},
|
|
|
|
|
2012-11-30 00:07:59 -08:00
|
|
|
/**
|
|
|
|
* Event handler.
|
|
|
|
*/
|
|
|
|
handleEvent: function ToolSidebar_eventHandler(event) {
|
|
|
|
if (event.type == "select") {
|
2013-06-24 06:24:00 -07:00
|
|
|
if (this._currentTool == this.getCurrentTabID()) {
|
|
|
|
// Tool hasn't changed.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-11-30 00:07:59 -08:00
|
|
|
let previousTool = this._currentTool;
|
|
|
|
this._currentTool = this.getCurrentTabID();
|
|
|
|
if (previousTool) {
|
2013-05-24 03:26:17 -07:00
|
|
|
this._telemetry.toolClosed(previousTool);
|
2012-11-30 00:07:59 -08:00
|
|
|
this.emit(previousTool + "-unselected");
|
|
|
|
}
|
|
|
|
|
2013-05-24 03:26:17 -07:00
|
|
|
this._telemetry.toolOpened(this._currentTool);
|
2012-11-30 00:07:59 -08:00
|
|
|
this.emit(this._currentTool + "-selected");
|
|
|
|
this.emit("select", this._currentTool);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Toggle sidebar's visibility state.
|
|
|
|
*/
|
|
|
|
toggle: function ToolSidebar_toggle() {
|
|
|
|
if (this._tabbox.hasAttribute("hidden")) {
|
|
|
|
this.show();
|
|
|
|
} else {
|
|
|
|
this.hide();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Show the sidebar.
|
|
|
|
*/
|
|
|
|
show: function ToolSidebar_show() {
|
2013-06-13 16:41:00 -07:00
|
|
|
if (this._width) {
|
|
|
|
this._tabbox.width = this._width;
|
|
|
|
}
|
2012-11-30 00:07:59 -08:00
|
|
|
this._tabbox.removeAttribute("hidden");
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Show the sidebar.
|
|
|
|
*/
|
|
|
|
hide: function ToolSidebar_hide() {
|
2013-06-13 16:41:00 -07:00
|
|
|
Services.prefs.setIntPref("devtools.toolsidebar-width." + this._uid, this._tabbox.width);
|
2012-11-30 00:07:59 -08:00
|
|
|
this._tabbox.setAttribute("hidden", "true");
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the window containing the tab content.
|
|
|
|
*/
|
|
|
|
getWindowForTab: function ToolSidebar_getWindowForTab(id) {
|
|
|
|
if (!this._tabs.has(id)) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
let panel = this._panelDoc.getElementById(this._tabs.get(id).linkedPanel);
|
|
|
|
return panel.firstChild.contentWindow;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Clean-up.
|
|
|
|
*/
|
|
|
|
destroy: function ToolSidebar_destroy() {
|
2012-12-13 05:03:55 -08:00
|
|
|
if (this._destroyed) {
|
2013-07-11 00:12:20 -07:00
|
|
|
return promise.resolve(null);
|
2012-12-13 05:03:55 -08:00
|
|
|
}
|
|
|
|
this._destroyed = true;
|
|
|
|
|
2013-06-13 16:41:00 -07:00
|
|
|
Services.prefs.setIntPref("devtools.toolsidebar-width." + this._uid, this._tabbox.width);
|
|
|
|
|
2012-12-17 11:29:08 -08:00
|
|
|
this._tabbox.tabpanels.removeEventListener("select", this, true);
|
2012-11-30 00:07:59 -08:00
|
|
|
|
|
|
|
while (this._tabbox.tabpanels.hasChildNodes()) {
|
|
|
|
this._tabbox.tabpanels.removeChild(this._tabbox.tabpanels.firstChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (this._tabbox.tabs.hasChildNodes()) {
|
|
|
|
this._tabbox.tabs.removeChild(this._tabbox.tabs.firstChild);
|
|
|
|
}
|
|
|
|
|
2013-05-24 03:26:17 -07:00
|
|
|
if (this._currentTool) {
|
|
|
|
this._telemetry.toolClosed(this._currentTool);
|
|
|
|
}
|
|
|
|
|
2012-11-30 00:07:59 -08:00
|
|
|
this._tabs = null;
|
|
|
|
this._tabbox = null;
|
|
|
|
this._panelDoc = null;
|
|
|
|
this._toolPanel = null;
|
2012-12-13 05:03:55 -08:00
|
|
|
|
2013-07-11 00:12:20 -07:00
|
|
|
return promise.resolve(null);
|
2012-11-30 00:07:59 -08:00
|
|
|
},
|
|
|
|
}
|