Bug 912891 - [app manager] Open the toolbox in the app manager. r=ochameau

This commit is contained in:
Paul Rouget 2013-11-07 09:14:22 -05:00
parent 79d2b45bb6
commit 0dcfd9bc8c
7 changed files with 185 additions and 87 deletions

View File

@ -1078,7 +1078,7 @@ pref("devtools.commands.dir", "");
// Enable the app manager
pref("devtools.appmanager.enabled", true);
pref("devtools.appmanager.firstrun", true);
pref("devtools.appmanager.lastTab", "help");
pref("devtools.appmanager.manifestEditor.enabled", false);
// Toolbox preferences

View File

@ -162,16 +162,13 @@ let UI = {
if (!this.connected) {
return;
}
let app = this.store.object.apps.all.filter(a => a.manifestURL == manifest)[0];
getTargetForApp(this.connection.client,
this.listTabsResponse.webappsActor,
manifest).then((target) => {
gDevTools.showToolbox(target,
null,
devtools.Toolbox.HostType.WINDOW).then(toolbox => {
this.connection.once(Connection.Events.DISCONNECTED, () => {
toolbox.destroy();
});
});
top.UI.openAndShowToolboxForTarget(target, app.name, app.iconURL);
}, console.error);
},

View File

@ -7,76 +7,176 @@ Cu.import("resource:///modules/devtools/gDevTools.jsm");
const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const {require} = devtools;
const {ConnectionManager, Connection} = require("devtools/client/connection-manager");
const promise = require("sdk/core/promise");
const prefs = require('sdk/preferences/service');
let connection;
window.addEventListener("message", function(event) {
try {
let json = JSON.parse(event.data);
switch (json.name) {
case "connection":
let cid = +json.cid;
for (let c of ConnectionManager.connections) {
if (c.uid == cid) {
connection = c;
onNewConnection();
break;
}
}
break;
case "closeHelp":
selectTab("projects");
break;
default:
Cu.reportError("Unknown message: " + json.name);
let UI = {
_toolboxTabCursor: 0,
_handledTargets: new Map(),
connection: null,
init: function() {
this.onLoad = this.onLoad.bind(this);
this.onUnload = this.onUnload.bind(this);
this.onMessage = this.onMessage.bind(this);
this.onConnected = this.onConnected.bind(this);
this.onDisconnected = this.onDisconnected.bind(this);
window.addEventListener("load", this.onLoad);
window.addEventListener("unload", this.onUnload);
window.addEventListener("message", this.onMessage);
},
onLoad: function() {
window.removeEventListener("load", this.onLoad);
let defaultPanel = prefs.get("devtools.appmanager.lastTab");
let panelExists = !!document.querySelector("." + defaultPanel + "-panel");
this.selectTab(panelExists ? defaultPanel : "projects");
},
onUnload: function() {
window.removeEventListener("unload", this.onUnload);
window.removeEventListener("message", this.onMessage);
if (this.connection) {
this.connection.off(Connection.Status.CONNECTED, this.onConnected);
this.connection.off(Connection.Status.DISCONNECTED, this.onDisconnected);
}
} catch(e) { Cu.reportError(e); }
},
// Forward message
let panels = document.querySelectorAll(".panel");
for (let frame of panels) {
frame.contentWindow.postMessage(event.data, "*");
}
}, false);
onMessage: function(event) {
try {
let json = JSON.parse(event.data);
switch (json.name) {
case "connection":
let cid = +json.cid;
for (let c of ConnectionManager.connections) {
if (c.uid == cid) {
this.onNewConnection(c);
break;
}
}
break;
case "closeHelp":
this.selectTab("projects");
break;
case "toolbox-raise":
this.selectTab(json.uid);
break;
case "toolbox-close":
this.closeToolboxTab(json.uid);
break;
default:
Cu.reportError("Unknown message: " + json.name);
}
} catch(e) { Cu.reportError(e); }
window.addEventListener("unload", function onUnload() {
window.removeEventListener("unload", onUnload);
if (connection) {
connection.off(Connection.Status.CONNECTED, onConnected);
connection.off(Connection.Status.DISCONNECTED, onDisconnected);
}
});
// Forward message
let panels = document.querySelectorAll(".panel");
for (let frame of panels) {
frame.contentWindow.postMessage(event.data, "*");
}
},
function onNewConnection() {
connection.on(Connection.Status.CONNECTED, onConnected);
connection.on(Connection.Status.DISCONNECTED, onDisconnected);
}
selectTabFromButton: function(button) {
if (!button.hasAttribute("panel"))
return;
this.selectTab(button.getAttribute("panel"));
},
function onConnected() {
document.querySelector("#content").classList.add("connected");
}
selectTab: function(panel) {
let isToolboxTab = false;
for (let type of ["button", "panel"]) {
let oldSelection = document.querySelector("." + type + "[selected]");
let newSelection = document.querySelector("." + panel + "-" + type);
if (oldSelection) oldSelection.removeAttribute("selected");
if (newSelection) {
newSelection.scrollIntoView(false);
newSelection.setAttribute("selected", "true");
if (newSelection.classList.contains("toolbox")) {
isToolboxTab = true;
}
}
}
if (!isToolboxTab) {
prefs.set("devtools.appmanager.lastTab", panel);
}
},
function onDisconnected() {
document.querySelector("#content").classList.remove("connected");
}
onNewConnection: function(connection) {
this.connection = connection;
this.connection.on(Connection.Status.CONNECTED, this.onConnected);
this.connection.on(Connection.Status.DISCONNECTED, this.onDisconnected);
},
function selectTab(id) {
for (let type of ["button", "panel"]) {
let oldSelection = document.querySelector("." + type + "[selected]");
let newSelection = document.querySelector("." + id + "-" + type);
if (oldSelection) oldSelection.removeAttribute("selected");
if (newSelection) newSelection.setAttribute("selected", "true");
}
if (id != "help") {
// Might be the first time the user is accessing the actual app manager
prefs.set("devtools.appmanager.firstrun", false);
onConnected: function() {
document.querySelector("#content").classList.add("connected");
},
onDisconnected: function() {
for (let [,toolbox] of this._handledTargets) {
if (toolbox) {
toolbox.destroy();
}
}
this._handledTargets.clear();
document.querySelector("#content").classList.remove("connected");
},
createToolboxTab: function(name, iconURL, uid) {
let button = document.createElement("button");
button.className = "button toolbox " + uid + "-button";
button.setAttribute("panel", uid);
button.textContent = name;
button.setAttribute("style", "background-image: url(" + iconURL + ")");
let toolboxTabs = document.querySelector("#toolbox-tabs");
toolboxTabs.appendChild(button);
let iframe = document.createElement("iframe");
iframe.setAttribute("flex", "1");
iframe.className = "panel toolbox " + uid + "-panel";
let panels = document.querySelector("#tab-panels");
panels.appendChild(iframe);
this.selectTab(uid);
return iframe;
},
closeToolboxTab: function(uid) {
let buttonToDestroy = document.querySelector("." + uid + "-button");
let panelToDestroy = document.querySelector("." + uid + "-panel");
if (buttonToDestroy.hasAttribute("selected")) {
let lastTab = prefs.get("devtools.appmanager.lastTab");
this.selectTab(lastTab);
}
buttonToDestroy.remove();
panelToDestroy.remove();
},
openAndShowToolboxForTarget: function(target, name, icon) {
let host = devtools.Toolbox.HostType.CUSTOM;
if (!this._handledTargets.has(target)) {
let uid = "uid" + this._toolboxTabCursor++;
let iframe = this.createToolboxTab(name, icon, uid);
let options = { customIframe: iframe , uid: uid };
this._handledTargets.set(target, null);
return gDevTools.showToolbox(target, null, host, options).then(toolbox => {
this._handledTargets.set(target, toolbox);
toolbox.once("destroyed", () => {
this._handledTargets.delete(target)
});
});
} else {
let toolbox = this._handledTargets.get(target);
if (!toolbox) {
// Target is handled, but toolbox is still being
// created.
return promise.resolve(null);
}
return gDevTools.showToolbox(target, null, host);
}
}
}
let firstRun = prefs.get("devtools.appmanager.firstrun");
if (firstRun) {
selectTab("help");
} else {
selectTab("projects");
}
UI.init();

View File

@ -22,11 +22,11 @@
<vbox id="root" flex="1">
<hbox id="content" flex="1">
<vbox id="tabs">
<button class="button projects-button" onclick="selectTab('projects')">&index.projects2;</button>
<button class="button device-button" onclick="selectTab('device')">&index.device2;</button>
<spacer flex="1"/>
<button class="button help-button" onclick="selectTab('help')">&index.help;</button>
<vbox id="tabs" onclick="UI.selectTabFromButton(event.target)">
<button class="button projects-button" panel="projects">&index.projects2;</button>
<button class="button device-button" panel="device">&index.device2;</button>
<vbox id="toolbox-tabs" flex="1"/>
<button class="button help-button" panel="help">&index.help;</button>
</vbox>
<hbox id="tab-panels" flex="1">
<iframe flex="1" class="panel projects-panel" src="chrome://browser/content/devtools/app-manager/projects.xhtml"/>

View File

@ -356,25 +356,15 @@ let UI = {
loop(0);
return deferred.promise;
};
let onTargetReady = (target) => {
// Finally, when it's finally opened, display the toolbox
let deferred = promise.defer();
gDevTools.showToolbox(target,
null,
devtools.Toolbox.HostType.WINDOW).then(toolbox => {
this.connection.once(Connection.Events.DISCONNECTED, () => {
toolbox.destroy();
});
deferred.resolve(toolbox);
});
return deferred.promise;
};
// First try to open the app
this.start(project)
.then(null, onFailedToStart)
.then(onStarted)
.then(onTargetReady)
.then((target) =>
top.UI.openAndShowToolboxForTarget(target,
project.manifest.name,
project.icon))
.then(() => {
// And only when the toolbox is opened, release the button
button.disabled = false;

View File

@ -12,6 +12,7 @@
#banners-and-logs {
display: flex;
flex-grow: 1;
}
#logs {

View File

@ -14,6 +14,10 @@
background: #252C33;
}
#toolbox-tabs {
overflow-y: auto;
}
.button {
width: 80px;
height: 85px;
@ -54,6 +58,12 @@
display: none;
}
.button.toolbox {
background-repeat: no-repeat;
background-position: center 15px;
background-size: 40px 40px;
}
.projects-button {
background: url('chrome://browser/skin/devtools/app-manager/index-icons.svg') no-repeat;
background-position: left -5px;