Bug 683954 - [Layout] Implement an abstract view of the layout of the selected node. r=dcamp, r=jwalker
authorPaul Rouget <paul@mozilla.com>
Mon, 12 Mar 2012 14:39:56 +0100
changeset 95368 dde2fce2058af9c91db9486d9329c7896f2074d8
parent 95367 1eaf11b3cb5f0d3f265acad0d9b27b384701ad8e
child 95369 fa8ef24d0e7e991a34e9acc6986aebc2446b7478
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdcamp, jwalker
bugs683954
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 683954 - [Layout] Implement an abstract view of the layout of the selected node. r=dcamp, r=jwalker
browser/app/profile/firefox.js
browser/base/content/highlighter.css
browser/devtools/Makefile.in
browser/devtools/highlighter/inspector.jsm
browser/devtools/jar.mn
browser/devtools/layoutview/LayoutView.jsm
browser/devtools/layoutview/Makefile.in
browser/devtools/layoutview/test/Makefile.in
browser/devtools/layoutview/test/browser_layoutview.js
browser/devtools/layoutview/view.css
browser/devtools/layoutview/view.xhtml
browser/locales/en-US/chrome/browser/devtools/layoutview.dtd
browser/locales/jar.mn
browser/themes/gnomestripe/devtools/layout-background.png
browser/themes/gnomestripe/devtools/layout-buttons.png
browser/themes/gnomestripe/devtools/layoutview.css
browser/themes/gnomestripe/jar.mn
browser/themes/pinstripe/devtools/layout-background.png
browser/themes/pinstripe/devtools/layout-buttons.png
browser/themes/pinstripe/devtools/layoutview.css
browser/themes/pinstripe/jar.mn
browser/themes/winstripe/devtools/layout-background.png
browser/themes/winstripe/devtools/layout-buttons.png
browser/themes/winstripe/devtools/layoutview.css
browser/themes/winstripe/jar.mn
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1044,16 +1044,20 @@ pref("devtools.errorconsole.enabled", fa
 
 // Enable the Inspector
 pref("devtools.inspector.enabled", true);
 pref("devtools.inspector.htmlHeight", 112);
 pref("devtools.inspector.htmlPanelOpen", false);
 pref("devtools.inspector.sidebarOpen", false);
 pref("devtools.inspector.activeSidebar", "ruleview");
 
+// Enable the Layout View
+pref("devtools.layoutview.enabled", false);
+pref("devtools.layoutview.open", false);
+
 // Enable the Debugger
 pref("devtools.debugger.enabled", false);
 
 // The default Debugger UI height
 pref("devtools.debugger.ui.height", 250);
 
 // Enable the style inspector
 pref("devtools.styleinspector.enabled", true);
--- a/browser/base/content/highlighter.css
+++ b/browser/base/content/highlighter.css
@@ -95,8 +95,20 @@ html|*#highlighter-nodeinfobar-tagname {
 
 html|*#highlighter-nodeinfobar-tagname {
   text-transform: lowercase;
 }
 
 .devtools-toolbarbutton:not([label]) > .toolbarbutton-text {
   display: none;
 }
+
+#inspector-layoutview-container > iframe {
+  -moz-transition-property: height;
+  -moz-transition-duration: 0.1s;
+  /* header size */
+  height: 22px;
+}
+
+#inspector-layoutview-container > iframe[open] {
+  /* header size + layout view size: 22px + 155px */
+  height: 177px;
+}
--- a/browser/devtools/Makefile.in
+++ b/browser/devtools/Makefile.in
@@ -50,12 +50,13 @@ DIRS = \
   highlighter \
   webconsole \
   sourceeditor \
   styleeditor \
   styleinspector \
   tilt \
   scratchpad \
   debugger \
+  layoutview \
   shared \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/browser/devtools/highlighter/inspector.jsm
+++ b/browser/devtools/highlighter/inspector.jsm
@@ -51,16 +51,17 @@ const Ci = Components.interfaces;
 const Cr = Components.results;
 
 var EXPORTED_SYMBOLS = ["InspectorUI"];
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource:///modules/TreePanel.jsm");
 Cu.import("resource:///modules/highlighter.jsm");
+Cu.import("resource:///modules/devtools/LayoutView.jsm");
 Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
 
 // Inspector notifications dispatched through the nsIObserverService.
 const INSPECTOR_NOTIFICATIONS = {
   // Fires once the Inspector completes the initialization and opens up on
   // screen.
   OPENED: "inspector-opened",
 
@@ -1400,16 +1401,22 @@ function InspectorStyleSidebar(aOptions)
 
 InspectorStyleSidebar.prototype = {
 
   get visible() !this._box.hasAttribute("hidden"),
   get activePanel() this._deck.selectedPanel._toolID,
 
   destroy: function ISS_destroy()
   {
+    // close the Layout View
+    if (this._layoutview) {
+      this._layoutview.destroy();
+      this._layoutview = null;
+    }
+
     for each (let toolID in Object.getOwnPropertyNames(this._tools)) {
       this.removeTool(toolID);
     }
     delete this._tools;
     this._teardown();
   },
 
   /**
@@ -1509,20 +1516,29 @@ InspectorStyleSidebar.prototype = {
     this._box.removeAttribute("hidden");
     this._splitter.removeAttribute("hidden");
     this._toggleButton.checked = true;
 
     this._showDefault();
 
     this._inspector._sidebarOpen = true;
     Services.prefs.setBoolPref("devtools.inspector.sidebarOpen", true);
+
+    // Instantiate the Layout View if needed.
+    if (Services.prefs.getBoolPref("devtools.layoutview.enabled")
+        && !this._layoutview) {
+      this._layoutview = new LayoutView({
+        document: this._chromeDoc,
+        inspector: this._inspector,
+      });
+    }
   },
 
   /**
-   * Hides the sidebar, updating the stored visiblity pref.
+   * Hides the sidebar, updating the stored visibility pref.
    */
   hide: function ISS_hide()
   {
     this._teardown();
     this._inspector._sidebarOpen = false;
     Services.prefs.setBoolPref("devtools.inspector.sidebarOpen", false);
   },
 
--- a/browser/devtools/jar.mn
+++ b/browser/devtools/jar.mn
@@ -4,14 +4,16 @@ browser.jar:
 *   content/browser/scratchpad.xul                (scratchpad/scratchpad.xul)
     content/browser/scratchpad.js                 (scratchpad/scratchpad.js)
     content/browser/splitview.css                 (shared/splitview.css)
 *   content/browser/styleeditor.xul               (styleeditor/styleeditor.xul)
     content/browser/styleeditor.css               (styleeditor/styleeditor.css)
     content/browser/devtools/csshtmltree.xul      (styleinspector/csshtmltree.xul)
     content/browser/devtools/cssruleview.xul      (styleinspector/cssruleview.xul)
     content/browser/devtools/styleinspector.css   (styleinspector/styleinspector.css)
+*   content/browser/devtools/layoutview/view.xhtml  (layoutview/view.xhtml)
+    content/browser/devtools/layoutview/view.css  (layoutview/view.css)
     content/browser/orion.js                      (sourceeditor/orion/orion.js)
 *   content/browser/source-editor-overlay.xul     (sourceeditor/source-editor-overlay.xul)
 *   content/browser/debugger.xul                  (debugger/debugger.xul)
     content/browser/debugger.css                  (debugger/debugger.css)
     content/browser/debugger-controller.js        (debugger/debugger-controller.js)
     content/browser/debugger-view.js              (debugger/debugger-view.js)
new file mode 100644
--- /dev/null
+++ b/browser/devtools/layoutview/LayoutView.jsm
@@ -0,0 +1,317 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla Layout Module.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2012
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Paul Rouget <paul@mozilla.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+"use strict";
+
+const Cu = Components.utils;
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource:///modules/inspector.jsm");
+Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
+
+var EXPORTED_SYMBOLS = ["LayoutView"];
+
+function LayoutView(aOptions)
+{
+  this.chromeDoc = aOptions.document;
+  this.inspector = aOptions.inspector;
+  this.browser = this.inspector.chromeWindow.gBrowser;
+
+  this.init();
+}
+
+LayoutView.prototype = {
+  init: function LV_init() {
+
+    this.update = this.update.bind(this);
+    this.onMessage = this.onMessage.bind(this);
+
+    this.isOpen = false;
+    this.documentReady = false;
+
+    // Is the layout view was open before?
+    if (!("_layoutViewIsOpen" in this.inspector)) {
+      this.inspector._layoutViewIsOpen =
+        Services.prefs.getBoolPref("devtools.layoutview.open");
+    }
+
+    // We update the values when:
+    //  a node is locked
+    //  we get the MozAfterPaint event and the node is locked
+    function onLock() {
+      this.undim();
+      this.update();
+      // We make sure we never add 2 listeners.
+      if (!this.trackingPaint) {
+        this.browser.addEventListener("MozAfterPaint", this.update, true);
+        this.trackingPaint = true;
+      }
+    }
+
+    function onUnlock() {
+      this.browser.removeEventListener("MozAfterPaint", this.update, true);
+      this.trackingPaint = false;
+      this.dim();
+    }
+
+    this.onLock = onLock.bind(this);
+    this.onUnlock = onUnlock.bind(this);
+    this.inspector.on("locked", this.onLock);
+    this.inspector.on("unlocked", this.onUnlock);
+
+    // Build the layout view in the sidebar.
+    this.buildView();
+
+    // Get messages from the iframe.
+    this.inspector.chromeWindow.addEventListener("message", this.onMessage, true);
+
+    // Store for the different dimensions of the node.
+    // 'selector' refers to the element that holds the value in view.xhtml;
+    // 'property' is what we are measuring;
+    // 'value' is the computed dimension, computed in update().
+    this.map = {
+      marginTop: {selector: ".margin.top > span",
+                  property: "margin-top",
+                  value: undefined},
+      marginBottom: {selector: ".margin.bottom > span",
+                  property: "margin-bottom",
+                  value: undefined},
+      marginLeft: {selector: ".margin.left > span",
+                  property: "margin-left",
+                  value: undefined},
+      marginRight: {selector: ".margin.right > span",
+                  property: "margin-right",
+                  value: undefined},
+      paddingTop: {selector: ".padding.top > span",
+                  property: "padding-top",
+                  value: undefined},
+      paddingBottom: {selector: ".padding.bottom > span",
+                  property: "padding-bottom",
+                  value: undefined},
+      paddingLeft: {selector: ".padding.left > span",
+                  property: "padding-left",
+                  value: undefined},
+      paddingRight: {selector: ".padding.right > span",
+                  property: "padding-right",
+                  value: undefined},
+      borderTop: {selector: ".border.top > span",
+                  property: "border-top-width",
+                  value: undefined},
+      borderBottom: {selector: ".border.bottom > span",
+                  property: "border-bottom-width",
+                  value: undefined},
+      borderLeft: {selector: ".border.left > span",
+                  property: "border-left-width",
+                  value: undefined},
+      borderRight: {selector: ".border.right > span",
+                  property: "border-right-width",
+                  value: undefined},
+    };
+  },
+
+  /**
+   * Destroy the nodes. Remove listeners.
+   */
+  destroy: function LV_destroy() {
+    this.inspector.removeListener("locked", this.onLock);
+    this.inspector.removeListener("unlocked", this.onUnlock);
+    this.browser.removeEventListener("MozAfterPaint", this.update, true);
+    this.inspector.chromeWindow.removeEventListener("message", this.onMessage, true);
+    this.close();
+    this.iframe = null;
+    this.view.parentNode.removeChild(this.view);
+  },
+
+  /**
+   * Build the Layout container:
+   *
+   * <vbox id="inspector-layoutview-container">
+   *  <iframe src="chrome://browser/content/devtools/layoutview/view.xhtml"/>
+   * </vbox>
+   */
+  buildView: function LV_buildPanel() {
+    this.iframe = this.chromeDoc.createElement("iframe");
+    this.iframe.setAttribute("src", "chrome://browser/content/devtools/layoutview/view.xhtml");
+
+    this.view = this.chromeDoc.createElement("vbox");
+    this.view.id = "inspector-layoutview-container";
+    this.view.appendChild(this.iframe);
+
+    let sidebar = this.chromeDoc.getElementById("devtools-sidebar-box");
+    sidebar.appendChild(this.view);
+  },
+
+  /**
+   * Called when the iframe is loaded.
+   */
+  onDocumentReady: function LV_onDocumentReady() {
+    this.documentReady = true;
+    this.doc = this.iframe.contentDocument;
+
+    // We can't do that earlier because open() and close() need to do stuff
+    // inside the iframe.
+
+    if (this.inspector.locked)
+      this.onLock();
+    else
+      this.onUnlock();
+
+    if (this.inspector._layoutViewIsOpen) {
+      this.open();
+    } else {
+      this.close();
+    }
+
+  },
+
+  /**
+   * This is where we get messages from the layout view iframe.
+   */
+  onMessage: function LV_onMessage(e) {
+    switch (e.data) {
+      case "layoutview-toggle-view":
+        this.toggle(true);
+        break;
+      case "layoutview-ready":
+        this.onDocumentReady();
+        break;
+      default:
+        break;
+    }
+  },
+
+  /**
+   * Open the view container.
+   *
+   * @param aUserAction Is the action triggered by the user (click on the
+   * open/close button in the view)
+   */
+  open: function LV_open(aUserAction) {
+    this.isOpen = true;
+    if (this.documentReady)
+      this.doc.body.classList.add("open");
+    if (aUserAction) {
+      this.inspector._layoutViewIsOpen = true;
+      Services.prefs.setBoolPref("devtools.layoutview.open", true);
+    }
+    this.iframe.setAttribute("open", "true");
+    this.update();
+  },
+
+  /**
+   * Close the view container.
+   *
+   * @param aUserAction Is the action triggered by the user (click on the
+   * open/close button in the view)
+   */
+  close: function LV_close(aUserAction) {
+    this.isOpen = false;
+    if (this.documentReady)
+      this.doc.body.classList.remove("open");
+    if (aUserAction) {
+      this.inspector._layoutViewIsOpen = false;
+      Services.prefs.setBoolPref("devtools.layoutview.open", false);
+    }
+    this.iframe.removeAttribute("open");
+  },
+
+  /**
+   * Toggle view container state (open/close).
+   *
+   * @param aUserAction Is the action triggered by the user (click on the
+   * open/close button in the view)
+   */
+  toggle: function LV_toggle(aUserAction) {
+    this.isOpen ? this.close(aUserAction):this.open(aUserAction);
+  },
+
+  /**
+   * Hide the layout boxes. No node are selected.
+   */
+  dim: function LV_dim() {
+    if (!this.documentReady) return;
+    this.doc.body.classList.add("dim");
+  },
+
+  /**
+   * Show the layout boxes. A node is selected.
+   */
+  undim: function LV_dim() {
+    if (!this.documentReady) return;
+    this.doc.body.classList.remove("dim");
+  },
+
+  /**
+   * Compute the dimensions of the node and update the values in
+   * the layoutview/view.xhtml document.
+   */
+  update: function LV_update() {
+    let node = this.inspector.selection;
+    if (!node || !this.documentReady) return;
+
+    // First, we update the first part of the layout view, with
+    // the size of the element.
+
+    let clientRect = node.getBoundingClientRect();
+    let width = Math.round(clientRect.width);
+    let height = Math.round(clientRect.height);
+    this.doc.querySelector("#element-size").textContent =  width + "x" + height;
+
+    // If the view is closed, no need to do anything more.
+    if (!this.isOpen) return;
+
+    // We compute and update the values of margins & co.
+    let style = this.browser.contentWindow.getComputedStyle(node);;
+
+    for (let i in this.map) {
+      let selector = this.map[i].selector;
+      let property = this.map[i].property;
+      this.map[i].value = parseInt(style.getPropertyValue(property));
+      let span = this.doc.querySelector(selector);
+      span.textContent = this.map[i].value;
+    }
+
+    width -= this.map.borderLeft.value + this.map.borderRight.value +
+             this.map.paddingLeft.value + this.map.paddingRight.value;
+
+    height -= this.map.borderTop.value + this.map.borderBottom.value +
+              this.map.paddingTop.value + this.map.paddingBottom.value;
+
+    this.doc.querySelector(".size > span").textContent = width + "x" + height;
+  },
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/layoutview/Makefile.in
@@ -0,0 +1,53 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is LayoutView Build Code.
+#
+# The Initial Developer of the Original Code is The Mozilla Foundation.
+#
+# Portions created by the Initial Developer are Copyright (C) 2012
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Paul Rouget <paul@mozilla.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+ifdef ENABLE_TESTS
+	DIRS += test
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+libs::
+	$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
new file mode 100644
--- /dev/null
+++ b/browser/devtools/layoutview/test/Makefile.in
@@ -0,0 +1,53 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2012
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Paul Rouget <paul@mozilla.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH     = ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = browser/devtools/layoutview/test
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+_BROWSER_FILES = \
+		browser_layoutview.js \
+		$(NULL)
+
+
+libs::	$(_BROWSER_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/devtools/layoutview/test/browser_layoutview.js
@@ -0,0 +1,134 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  waitForExplicitFinish();
+
+  Services.prefs.setBoolPref("devtools.layoutview.enabled", true);
+  Services.prefs.setBoolPref("devtools.inspector.sidebarOpen", true);
+
+  let doc;
+  let node;
+  let view;
+
+  // Expected values:
+  let res1 = [
+        {selector: "#element-size",              value: "160x160"},
+        {selector: ".size > span",               value: "100x100"},
+        {selector: ".margin.top > span",         value: 30},
+        {selector: ".margin.left > span",        value: 30},
+        {selector: ".margin.bottom > span",      value: 30},
+        {selector: ".margin.right > span",       value: 30},
+        {selector: ".padding.top > span",        value: 20},
+        {selector: ".padding.left > span",       value: 20},
+        {selector: ".padding.bottom > span",     value: 20},
+        {selector: ".padding.right > span",      value: 20},
+        {selector: ".border.top > span",         value: 10},
+        {selector: ".border.left > span",        value: 10},
+        {selector: ".border.bottom > span",      value: 10},
+        {selector: ".border.right > span",       value: 10},
+  ];
+
+  let res2 = [
+        {selector: "#element-size",              value: "160x210"},
+        {selector: ".size > span",               value: "100x150"},
+        {selector: ".margin.top > span",         value: 30},
+        {selector: ".margin.left > span",        value: 30},
+        {selector: ".margin.bottom > span",      value: 30},
+        {selector: ".margin.right > span",       value: 50},
+        {selector: ".padding.top > span",        value: 20},
+        {selector: ".padding.left > span",       value: 20},
+        {selector: ".padding.bottom > span",     value: 20},
+        {selector: ".padding.right > span",      value: 20},
+        {selector: ".border.top > span",         value: 10},
+        {selector: ".border.left > span",        value: 10},
+        {selector: ".border.bottom > span",      value: 10},
+        {selector: ".border.right > span",       value: 10},
+  ];
+
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function onload() {
+    gBrowser.selectedBrowser.removeEventListener("load", onload, true);
+    doc = content.document;
+    waitForFocus(setupTest, content);
+  }, true);
+
+  let style = "div { position: absolute; top: 42px; left: 42px; height: 100px; width: 100px; border: 10px solid black; padding: 20px; margin: 30px; }";
+  let html = "<style>" + style + "</style><div></div>"
+  content.location = "data:text/html," + encodeURIComponent(html);
+
+  function setupTest() {
+    node = doc.querySelector("div");
+    ok(node, "node found");
+
+    Services.obs.addObserver(openLayoutView,
+      InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
+    InspectorUI.toggleInspectorUI();
+  }
+
+  function openLayoutView() {
+    Services.obs.removeObserver(openLayoutView,
+      InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
+
+    info("Inspector open");
+
+    let highlighter = InspectorUI.highlighter;
+    highlighter.highlight(node);
+    highlighter.lock();
+
+    window.addEventListener("message", viewReady, true);
+  }
+
+  function viewReady(e) {
+    if (e.data != "layoutview-ready") return;
+
+    info("Layout view ready");
+
+    view = InspectorUI._sidebar._layoutview;
+
+    ok(!!view, "LayoutView document is alive.");
+
+    view.open();
+
+    ok(view.iframe.getAttribute("open"), "true", "View is open.");
+
+    test1();
+  }
+
+  function test1() {
+    let viewdoc = view.iframe.contentDocument;
+
+    for (let i = 0; i < res1.length; i++) {
+      let elt = viewdoc.querySelector(res1[i].selector);
+      is(elt.textContent, res1[i].value, res1[i].selector + " has the right value.");
+    }
+
+    InspectorUI.selection.style.height = "150px";
+    InspectorUI.selection.style.marginRight = "50px";
+
+    setTimeout(test2, 200); // Should be enough to get a MozAfterPaint event
+  }
+
+  function test2() {
+    let viewdoc = view.iframe.contentDocument;
+
+    for (let i = 0; i < res2.length; i++) {
+      let elt = viewdoc.querySelector(res2[i].selector);
+      is(elt.textContent, res2[i].value, res2[i].selector + " has the right value after style update.");
+    }
+
+    executeSoon(function() {
+      Services.obs.addObserver(finishUp,
+        InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
+      InspectorUI.closeInspectorUI();
+    });
+  }
+
+  function finishUp() {
+    Services.prefs.clearUserPref("devtools.layoutview.enabled");
+    Services.prefs.clearUserPref("devtools.inspector.sidebarOpen");
+    Services.obs.removeObserver(finishUp, InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED);
+    gBrowser.removeCurrentTab();
+    finish();
+  }
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/layoutview/view.css
@@ -0,0 +1,176 @@
+body, html {
+  height: 100%;
+  width: 100%;
+  overflow: hidden;
+}
+
+body {
+  margin: 0;
+  padding: 0;
+}
+
+#header {
+  -moz-box-sizing: border-box;
+  font: 12px/14px monospace;
+  width: 100%;
+  padding: 3px 4px;
+  display: -moz-box;
+}
+
+body[dir=rtl] > #header {
+  -moz-box-direction: reverse;
+}
+
+#header > span {
+  display: -moz-box;
+}
+
+#element-size {
+  -moz-box-flex: 1;
+}
+
+body[dir=rtl] > #header > #element-size {
+  -moz-box-pack: end;
+}
+
+#header:focus {
+  outline: none;
+}
+
+#main {
+  margin: 10px;
+  -moz-box-sizing: border-box;
+  width: -moz-calc(100% - 2 * 10px);
+  position: absolute;
+  border-width: 1px;
+  font: 10px/12px monospace;
+}
+
+#margins {
+  padding: 28px;
+}
+
+#content {
+  height: 20px;
+  border-width: 1px;
+}
+
+#padding {
+  border-width: 25px;
+}
+
+#borders {
+  border-width: 2px;
+  box-shadow: 0 0 16px black;
+}
+
+#main > p {
+  position: absolute;
+  pointer-events: none;
+}
+
+#main > p {
+  margin: 0;
+  text-align: center;
+}
+
+#main > p > span {
+  vertical-align: middle;
+  pointer-events: auto;
+  cursor: default;
+}
+
+.border.top {
+  left: 0; top: 23px;
+  width: 98px;
+}
+
+.border.bottom {
+  right: 0; bottom: 22px;
+  width: 98px;
+  top: auto;
+}
+
+.border.left {
+  top: 42px; left: 0;
+  width: 56px;
+}
+
+.border.right{
+  bottom: 42px; right: 0;
+  width: 56px;
+  top: auto;
+}
+
+.top, .bottom {
+  width: -moz-calc(100% - 2px);
+  text-align: center;
+}
+
+.margin.top {
+  top: 8px;
+}
+
+.margin.bottom {
+  bottom: 6px;
+}
+
+.padding.top {
+  top: 35px;
+}
+
+.padding.bottom {
+  bottom: 35px;
+}
+
+.size,
+.margin.left,
+.margin.right,
+.padding.left,
+.padding.right {
+  top: 0;
+  line-height: 132px;
+}
+
+.size {
+  width: -moz-calc(100% - 2px);
+}
+
+.margin.right,
+.margin.left {
+  width: 28px;
+}
+
+.padding.right,
+.padding.left {
+  width: 25px;
+}
+
+.margin.right {
+  right: 0;
+}
+
+.margin.left {
+  left: 0;
+}
+
+.padding.left {
+  left: 30px;
+}
+
+.padding.right {
+  right: 30px;
+}
+
+.tooltip {
+  position: absolute;
+  bottom: 0;
+  right: 2px;
+  pointer-events: none;
+}
+
+body.dim > #main,
+body.dim > #header > #element-size {
+  visibility: hidden;
+}
+
new file mode 100644
--- /dev/null
+++ b/browser/devtools/layoutview/view.xhtml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8"?>
+#ifdef 0
+<!-- ***** BEGIN LICENSE BLOCK *****
+   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+   -
+   - The contents of this file are subject to the Mozilla Public License Version
+   - 1.1 (the "License"); you may not use this file except in compliance with
+   - the License. You may obtain a copy of the License at
+   - http://www.mozilla.org/MPL/
+   -
+   - Software distributed under the License is distributed on an "AS IS" basis,
+   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+   - for the specific language governing rights and limitations under the
+   - License.
+   -
+   - The Original Code is LayoutView.
+   -
+   - The Initial Developer of the Original Code is
+   - The Mozilla Foundation.
+   - Portions created by the Initial Developer are Copyright (C) 2012
+   - the Initial Developer. All Rights Reserved.
+   -
+   - Contributor(s):
+   -   Paul Rouget <paul@mozilla.com> (original author)
+   -
+   - Alternatively, the contents of this file may be used under the terms of
+   - either the GNU General Public License Version 2 or later (the "GPL"), or
+   - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+   - in which case the provisions of the GPL or the LGPL are applicable instead
+   - of those above. If you wish to allow use of your version of this file only
+   - under the terms of either the GPL or the LGPL, and not to allow others to
+   - use your version of this file under the terms of the MPL, indicate your
+   - decision by deleting the provisions above and replace them with the notice
+   - and other provisions required by the GPL or the LGPL. If you do not delete
+   - the provisions above, a recipient may use your version of this file under
+   - the terms of any one of the MPL, the GPL or the LGPL.
+   -
+   - ***** END LICENSE BLOCK ***** -->
+#endif
+<!DOCTYPE html [
+<!ENTITY % layoutviewDTD SYSTEM "chrome://browser/locale/devtools/layoutview.dtd" >
+ %layoutviewDTD;
+]>
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <head>
+    <title>Layout View</title>
+
+    <script type="application/javascript;version=1.8">
+    <![CDATA[
+      let elts;
+      let tooltip;
+
+      const Ci = Components.interfaces;
+      const Cc = Components.classes;
+
+      window.onload = function() {
+
+        // Tooltip mechanism
+        elts = document.querySelectorAll("*[tooltip]");
+        tooltip = document.querySelector(".tooltip");
+        for (let i = 0; i < elts.length; i++) {
+          let elt = elts[i];
+          elt.addEventListener("mouseover", onmouseover, true);
+          elt.addEventListener("mouseout", onmouseout, true);
+        }
+
+        // Mark document as RTL or LTR:
+        let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].
+          getService(Ci.nsIXULChromeRegistry);
+        let dir = chromeReg.isLocaleRTL("global");
+        document.body.setAttribute("dir", dir ? "rtl" : "ltr");
+
+        window.parent.postMessage("layoutview-ready", "*");
+      }
+
+      window.onunload = function() {
+        if (elts) {
+          for (let i = 0; i < elts.length; i++) {
+            let elt = elts[i];
+            elt.removeEventListener("mouseover", onmouseover, true);
+            elt.removeEventListener("mouseout", onmouseout, true);
+          }
+        }
+      }
+
+      function onmouseover(e) {
+        tooltip.textContent = e.target.getAttribute("tooltip");
+      }
+
+      function onmouseout(e) {
+        tooltip.textContent = "";
+      }
+
+      function toggleView() {
+        window.parent.postMessage("layoutview-toggle-view", "*");
+      }
+    ]]>
+    </script>
+
+    <link rel="stylesheet" href="chrome://browser/skin/devtools/layoutview.css" type="text/css"/>
+    <link rel="stylesheet" href="view.css" type="text/css"/>
+
+  </head>
+  <body>
+
+    <!-- Header: always visible, even when the view is closed. -->
+    <a onclick="toggleView()" href="#" id="header">
+        <span>&elementSize.label;</span>
+        <span id="element-size"></span>
+        <span id="togglebutton"></span>
+    </a>
+
+    <!-- Boxes: hidden when the view is closed. -->
+    <div id="main">
+
+      <div id="margins" tooltip="&margins.tooltip;">
+        <div id="borders" tooltip="&borders.tooltip;">
+          <div id="padding" tooltip="&padding.tooltip;">
+            <div id="content" tooltip="&content.tooltip;">
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <p class="border top"><span tooltip="border-top"></span></p>
+      <p class="border right"><span tooltip="border-right"></span></p>
+      <p class="border bottom"><span tooltip="border-bottom"></span></p>
+      <p class="border left"><span tooltip="border-left"></span></p>
+
+      <p class="margin top"><span tooltip="margin-top"></span></p>
+      <p class="margin right"><span tooltip="margin-right"></span></p>
+      <p class="margin bottom"><span tooltip="margin-bottom"></span></p>
+      <p class="margin left"><span tooltip="margin-left"></span></p>
+
+      <p class="padding top"><span tooltip="padding-top"></span></p>
+      <p class="padding right"><span tooltip="padding-right"></span></p>
+      <p class="padding bottom"><span tooltip="padding-bottom"></span></p>
+      <p class="padding left"><span tooltip="padding-left"></span></p>
+
+      <p class="size"><span tooltip="&content.tooltip;"></span></p>
+
+      <span class="tooltip"></span>
+
+    </div>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/locales/en-US/chrome/browser/devtools/layoutview.dtd
@@ -0,0 +1,21 @@
+<!-- LOCALIZATION NOTE : FILE This file contains the Layout View strings.
+  - The Layout View is the panel accessible at the bottom of the Inspector
+  - sidebar. -->
+
+<!-- LOCALIZATION NOTE : FILE The correct localization of this file might be to
+  - keep it in English, or another language commonly spoken among web developers.
+  - You want to make that choice consistent across the developer tools.
+  - A good criteria is the language in which you'd find the best
+  - documentation on web development on the web. -->
+
+<!ENTITY elementSize.label      "Element Size: ">
+
+
+<!-- LOCALIZATION NOTE (*.tooltip): These tooltips are not regular tooltips.
+  -  The text appears on the bottom right corner of the layout view when
+  -  the corresponding box is hovered. -->
+
+<!ENTITY margins.tooltip        "margins">
+<!ENTITY borders.tooltip        "borders">
+<!ENTITY padding.tooltip        "padding">
+<!ENTITY content.tooltip        "content">
--- a/browser/locales/jar.mn
+++ b/browser/locales/jar.mn
@@ -26,16 +26,17 @@
     locale/browser/devtools/scratchpad.dtd            (%chrome/browser/devtools/scratchpad.dtd)
     locale/browser/devtools/styleeditor.properties    (%chrome/browser/devtools/styleeditor.properties)
     locale/browser/devtools/styleeditor.dtd           (%chrome/browser/devtools/styleeditor.dtd)
     locale/browser/devtools/styleinspector.properties (%chrome/browser/devtools/styleinspector.properties)
     locale/browser/devtools/styleinspector.dtd        (%chrome/browser/devtools/styleinspector.dtd)
     locale/browser/devtools/webConsole.dtd            (%chrome/browser/devtools/webConsole.dtd)
     locale/browser/devtools/sourceeditor.properties   (%chrome/browser/devtools/sourceeditor.properties)
     locale/browser/devtools/sourceeditor.dtd          (%chrome/browser/devtools/sourceeditor.dtd)
+    locale/browser/devtools/layoutview.dtd            (%chrome/browser/devtools/layoutview.dtd)
     locale/browser/newTab.dtd                      (%chrome/browser/newTab.dtd)
     locale/browser/newTab.properties               (%chrome/browser/newTab.properties)
     locale/browser/openLocation.dtd                (%chrome/browser/openLocation.dtd)
     locale/browser/openLocation.properties         (%chrome/browser/openLocation.properties)
 *   locale/browser/pageInfo.dtd                    (%chrome/browser/pageInfo.dtd)
     locale/browser/pageInfo.properties             (%chrome/browser/pageInfo.properties)
     locale/browser/quitDialog.properties           (%chrome/browser/quitDialog.properties)
 *   locale/browser/safeMode.dtd                    (%chrome/browser/safeMode.dtd)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..87b0b855d2573ecca3a4d7ded942c63bd03521e4
GIT binary patch
literal 3217
zc$}q{=QkS+1I1}6RkO=}Jc?39X^o1#+Qvxi5Hls3*ds#BiY?TRQG2gOtv)DHJSeJG
z#0<4p?b^!Q_fL4w`#a~Jd(J)Qez~7+v_9x169X3m6%`c|@Rg?FA6NXZ=&%1bdGJW}
zk8z^3%uq&d4k#a(C!9*n-t9H~Z=eh84crh8v&VS!!v8d=HT89kwIuW%Bn=T#M#!he
zj?YY-q)nY=ATF|Iu5#vX&!O(}79IdgPX#M4MQfCjjkmHbS_S5#`r22`4x?`GrvdlZ
zbO_LT6ZirV^b#5T%JD7GDMZ^DtK$-?>l&u#77lWc0DDC0dqx>}MH`}GjJ$Ei=vWh<
zI8)zu5KO$8UxK-RA~Yb$A~4x9D8(u`)%q>oCM3-kn+^-jcpa8$7yjNpA`2dw?GTmo
zCOQ`plZV9RyC#$vyJJl~!_80;=H8J|bQIJl+QKKs(idli!CCvo+W5!W1iZ5ih=&Cx
zybemR3r@6un`9r73=c_hz^1+lO+|#^k>P2`h;+w@45!FU=cr7V==ZKMS+2NjH(ZW;
zY_3OKuIIZv&-i?=gaTATp?6{tI;qGfx!5PA#5c7RlUnA7FZWL?4@j>F%&ZE^{BU$V
z$^Osi&L~5W(X;;ph5r$Ed7K#)6@wE{Q_YxzleYa-W9Ai_%2w#Rr0S@6xpBovr4IPe
zSQIF(xoC&>+LGE7;0Tp+MR3<u)hrGOo?l(%?C4Cv44#>#(;7I}-Efv<sR@-Tg4v+q
ze|d2W??P768%LEuk1}Q5W&Z-diC!??h=TStudA<iiJ(2okHDFhU|M(no=57wQKDV-
zY~>Ze-B+1|2h&SKzrrFZjuN7!(^Tut@&`jrKQ(vj$1X_zo1C-7S7e|>1eY^hT6M8@
z;lVI7DV>{xlLppa`l79zQ}P)Xdm^6lMPZ0CJ{%(y;W*MSIka+`r52PM#m0tViFu%x
zIa4sW?U&BFY+t^8(B7K`Iwe<0CJoeQWp&G3@$Mqu+s1Mv>?5*LfAshXeV^_?n1jD*
zS2Epx@|LodKlm^nP?Qjd`C70OBq$Dk-?!^P9RFG}S|guu{DF|$=o^D6Q=rDIGtRug
z+;+JaRv-zRI0#Dexv53)W(!O~R-$U~xC^=BEL-PXgGzg=MZuO!hXxICVG&T-d>rmx
za&D5;SCh#JT`H+$<$GNH{j7zyJm6~;nbkK!t|<fm61=v0l#Y2<;8}Gd&NkJnFD25Y
zhAwj1rQ&;GDQdT2TEG~gkr6+yGn%CM-Tkly$~-G7UQu`j#JY*{alv{?CF;GRzo%?f
zjo1NUW)@c8>=Z5~;pE1d{Ey@(tV5862l)*5pdY`*jFI}FGAC;Sr+0FJ!0*GN0G?lw
z{3wc`RJN19SpL3RCOF#6^Dg)39Vd46idSBT7=FlCT?5&rGtLUXgZiK~)6JWYRbm~`
zvjVrqemz{*GP0<s=k0#MLN%0<M(x{_#!xOx*t^>k{V!bZ`M$|%$9<u$s2mf=_gQPq
zf>Yh2>Yuo)1y8tZ61RvBDzq=xG)WwRhn<k_yatD_`m%{jJH1xI&F$?qV=ayoWlHu!
zVy<-GELrat-7kq&Nu}*Q{t~|Xh~&ox&MwTOA_}(sSnS3ji?bACPyfA1Xt^#PT5qk;
z00r>BJR@Pj0%_PAIz$Z_zd;*e@;5W&=FQp)iN2DEpM`phf*0Bi>QU$$k-`+2U$bin
zUUo)&pZLGjZ919~Jzd(j?yp8*MxHiQcf^EKQw*x5OZ6mv2b=^hKQ6F5|L$%B>Q4Ok
zN$>LF;c?yg=kq}b1j4toL-<SCCRlM!dAlvB6?1&JRr(ns7aTN`?LxfR8^^J%vc$`!
z<q~(k4^~@KE|yu2fxh@?v6IqTBx_0!sDn010WH?o`sN)yi`2vhRIwen*};N=2;BV8
z@EIg2!myMR-Zx23+)N3oi#9v9qpek{3Ol4_Z!}_iL7+SDw-sLS^9*g(dm5voGtcqZ
zYTUrzTiW%sM%hm^l#?-vgY}5ky6Dr2I@FZz!-#g8<rz^3b~1@dPQPqgq_G^Ds<Beu
z9l<fnn`NK&Rdk`!cpLK5T|$ka6aHlLrC>b~U)AW^2N%DWUJM|;<Pcy%jgoNGH8|xH
zZaUEd*3pe6i0+qA$L8K<EbLD$B6DX|351^HWy^jk#*gjg3FLL|C-G{07Ua(s(;m*V
zq7TYgvy=LY`n2Dryh5&FtEAf*?PjW22dUoP#0Zd-Xe%Fy{5{9=c#LbHQ+6J(l8?WV
zP%8%6{&+qki8Y%4P##j1Ce+t-!K_?k8u7JP>*;r`z*;?7YNh+Ic*IX(l=I-EQyNRl
z5^LVxf^;p2*JSnKUF7xR>M{p1o-HgOS@+f8Q7O=v6}(jPldh&Y()GzR!fs4M*0G)l
zka!nRYiS|wY@}wzD01js;J!dO9!5`W^>z?^Po!0+)VUMY9K!i;1YK+dMdUcAE0OWd
zug&2L<23l>N8CzKD-TpgDYn&~EE8AZn^)Letu0VIGkIOC3743_Xc8d9jyt}YQr=nn
zb4B;8wDJ*CrmLsyjjwjf_<rr@cUz3A>0r@%nd~_mHc(^PgR9h6kc2`l2pfsXelM+K
z))`w<Vfu~58fi`k-kw<~3#7NDcd3*~h<vY!U}(=VTdm>>jlVswyFnW)wcJoRsbTu-
z2g`QDuyz@bf6Y>6<dhOOU$X2yIA$sSL)Xaj>B`jB5Sao%EL|D9@)+oXaa+{5m2Xom
zwmf$wqs0yf2Hv+!mqPe~ia(W1di`Q@7t-2*PB!D4CJ^>S^{yc=V!ckn3oUWVKENP{
z=@~|zqleSBeEcME54<^sh`^FOv$7#&o$@<nBll>=<3Rr)Kbrhb(_HD!2;qr`Yjo`7
zKF26%Bl`uoI)aoK-=)zJPGoKj^&6Cnp>$lpqoZ&|@a*rN)yViXzQN#@wzi9t<<7~)
z->12kmm5SIH=l7nf*YY4ZNulPJgfBca&HUmzju0mw7*O_r3{pwPp7d2>)l=Er<I}M
zekV>7uXt`6smtsMjJw@#2YDU#Pi@LN0`Ef4e*)B?qrjh<dh-k;1&uAwhp_&nY;V1I
zz+0az`EJ?K_jxZ#Ak)GF<UrFvdaL$B>VDEt<9vT!<pxsX)Ph@k7iCDZqkhkDJH~f~
zrl_oiL(;4SJ6pG)r*7XpywEpb>$2YPY>!-VrbR***^*82i;9jst(rbo9hL($M>J&)
zf2EtnI&PbrHUD@>Bpi;kd5x4R#`?`H(f5G8Rd_DZj2%8jauL_&cIpze8}&$4iLshp
zg0faN5wx?5x1{89yi8(%zEXed@sTrb@WXKcEpahlR+i|lOyue^Rp^g4M&=HM0fP+0
zdHZ$`;OxhTfcF_wMumA#*qj#2>cA3rq?LnnsQoqzRaAjPbM%^#4ddSs^?p)Qmd<f#
zPh`!}7b+KxjHS6dvtBi8)aGuyo}0hhT3;J58)tusv9NobL-w2*^Cm(Yi-k6^%mu{&
z*JML;UPGl7Yo5JT30)ivm%}Gt+JSA@n*Y1#<MuN=Oy1s+#vC~(4srZ${m_x;1W;8X
z+Q{GFvCA7gc*N52$ey%@Le}xug`P7gvQ8M%=uASRF@#^|OJ#ALhInC-hO&npssqdx
zJq~XT%0O&#`WELydSr#tbzzj@e#Gj)N_;Qux#hGLhgs${TqVJ^yV7x;6CSA{j0k5K
z!B|_NHZM@ssY4FVRe|#(aSA#S#s;5<3yOh1`-K6W?(B4hY8D^SW!LlQ)wdfD{79`*
z&1zuIADKjO%F{JVRsPzhTSs@n8#{uHc1*oM=6P01x5RD@L&ISmMS8TE&q;-Ft4YVS
zicibr$Z7E2o8sKJb4zp@4?{}z>H&@ncTMH=Oh||k`TIP%P`erEjF6Seky!JYpe)uY
z2a~`)v7~zTg+YzN01xZ9$R9)+gCfb<E4rT+?{E?YmzLf2N6t{v>Ac~2(pPv7TLJy$
z90P4nVuiCW1ZrY}5UQje!iwQM(nyuT1^{QS)kOAe1+0OMsXf$8mU5@=TO8L)ROhy&
zpLxGS9#CP6j@$i8tm$fhgVMFV(0NMPc7w2}SkGEt?x=iXIlekQzM8gnB?ir1HZ})e
zxTAvuuS)B-T#xr0{SWr`4+cvAkz1{vyHY6+Uw&mgD_`{I?ot7@K$-+~TkL-TO@Sk$
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a5904654909b4767962fd68a5e4d926d3dab3aa8
GIT binary patch
literal 1237
zc$@*%1S<Q9P)<h;3K|Lk000e1NJLTq001Na000sQ1^@s6Gb4N`00001b5ch_0Itp)
z=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyb@
z3_3FC)$uj}00dP@L_t(Y$IX^&Y!p=#$A5QU_5m%sEzCFpnp(hul|&OFqCg-9g$i1s
ziIudVq96%rVnTx91M&eSX-FU@pixn`LeaK1wiXg%FeZ&cN-#kljoaD>WV=h--KC}7
zK6dB&Vejg&U)&l#c$3N8nYsUS&;NhUoO9uSHiV`db|4#YtGg{ttO<+)VRh$0*l_?k
z>o=CIE8VpDiMjI&Y|~+LyRX-5ZEpPSTuak=fYO&XKev8k*|NFw3LZkF>5#;{eXDok
zTuW1X>-UX63Qadky!Ag+xILZ$A#CG-Ojlhg&5Up;G`p(&#X5l6hStiy-tK7a=O0gY
z+_*LfO#O=uXYrDf{K_|Xx#kxXW>#(~t#ttTp1iy;FabD)z@8Q{Nn8jqp|JS?ZjWcA
zdgnG78X9Z^hJXwp7jUG&W58WtyyM2TydxjHztUUZ5(DxbfJ+DwYy0^^{+Ze@+}&Ni
z;dGc47A?$qwet1wv#ZyR04@L_Y_ZVLU>9%&aPB{NxP0026$>OxT9g+8T<sTs={$5`
zUp>$p8XDAuuoVF=hhi&E9IbIgBH?DhPr`r`$Vp)sRm@}ET|VQ)(V8{StXeBln2)F=
zoq6cMKHrv#Dt-G~yZfb-;|Xs>#+RQSf4HH}>jUCy?TErAHWC6EiG;5Mmw~Zhz;9~0
zk-P7}p;b?<SXn5goB(MGVaqIge%04NC*Y4n!gGYcummy=n8AQwYPvB7bT-s^^@;K5
z(w%$W^#OeH(UC`5n(D7A8)Is%sjws!iUY&IXfWVUN-GZ^+~4=|mWtVL?Ap@<ObH=o
z0(vmu@6dE(6d0Bg&5~EK<UAPg$28sO2ijVi>Jc{ELICAV8_*vN_+zQqWGJSR%u?i^
zG|jkE2&9xqC9z9wsF>ZCZ};V%)v4yjZ-VNzFVz_<)?wNF@1g023oxp7?0WK*@~s1P
z-jfA)f`RPnz59Do*IJ(wp=F+?8zm`g?7%%W_W-$?Zdkw1Q&{DYlv5UG?0~Ut$2%{S
zl~)XZ_wA{iI`7FbDa}#0$KwD(DgXbJWqz-r^+KKyV)b+itdug2ltcgIP$CpIO*aJK
zT(@D<lCtvGCL7Mw&N%(mXCW!gi$JXYv^NU~D#rz2lU9Y0;|{0u=6~s75}9KOnVgvA
zcF&50!<j(*{MqI^p`iioO8cc@(=^+GTdL<cEFsGB<mJr*IcZHyX;o}mDkbdNfM{QD
zkA3U*x3#S7?5BZZAnWp_Uqhy84yanRNWEVG6l=P%G%GuMc}3L@t*^JouIf{?`%mAD
zL`#wJ>0E$N*r?ES<I%;BEnQQ+_q}NT94$*A>}g6IAG{MBJ67{y=FRI@e*#!kykx`f
z>b-r1MGNnOOtU8n(cR_CJ$|fa{vRDT&I(O8a)HH)eTMqA(;0SPTot%v-jo23t0TyC
zjvry*ci>v`Jd_E{R5eDVorj4QGonJqgRt`#mb)4)8RTK500000NkvXXu0mjfw*E~O
new file mode 100644
--- /dev/null
+++ b/browser/themes/gnomestripe/devtools/layoutview.css
@@ -0,0 +1,87 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is LayoutView.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2012
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Paul Rouget <paul@mozilla.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+body {
+  background: url(layout-background.png), -moz-radial-gradient(50% 70%, circle cover, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%);
+  color: hsl(210,100%,85%);
+  border-top: 1px solid black;
+  -moz-box-sizing: border-box;
+}
+
+#element-size {
+  color: hsl(210,100%,95%);
+}
+
+#main {
+  border-color: hsla(210,100%,85%,0.7);
+  border-style: dotted;
+}
+
+#main > .border {
+  color: hsl(210,53%,45%);
+}
+
+.border > span {
+  background-color: hsl(210,100%,85%);
+  border-radius: 2px;
+  padding: 0 4px;
+}
+
+#content {
+  border-color: hsla(210,100%,85%,0.7);
+  border-style: dotted 
+}
+
+#padding {
+  border-color: hsla(210,100%,85%,0.2);
+  border-style: solid;
+}
+
+#borders {
+  border-style: solid;
+  border-color: hsl(210,100%,85%);
+}
+
+#togglebutton {
+  background-image: url(layout-buttons.png);
+  width: 18px;
+  height: 18px;
+  margin-top: -3px;
+}
+
+body.open > #header > #togglebutton {
+  background-position: -18px 0;
+}
--- a/browser/themes/gnomestripe/jar.mn
+++ b/browser/themes/gnomestripe/jar.mn
@@ -133,16 +133,19 @@ browser.jar:
   skin/classic/browser/devtools/debugger.css          (devtools/debugger.css)
   skin/classic/browser/devtools/magnifying-glass.png  (devtools/magnifying-glass.png)
   skin/classic/browser/devtools/itemToggle.png        (devtools/itemToggle.png)
   skin/classic/browser/devtools/itemArrow-rtl.png     (devtools/itemArrow-rtl.png)
   skin/classic/browser/devtools/itemArrow-ltr.png     (devtools/itemArrow-ltr.png)
   skin/classic/browser/devtools/inspect-button.png    (devtools/inspect-button.png)
   skin/classic/browser/devtools/dropmarker.png        (devtools/dropmarker.png)
   skin/classic/browser/devtools/treepanel-button.png  (devtools/treepanel-button.png)
+  skin/classic/browser/devtools/layout-background.png (devtools/layout-background.png)
+  skin/classic/browser/devtools/layoutview.css        (devtools/layoutview.css)
+  skin/classic/browser/devtools/layout-buttons.png    (devtools/layout-buttons.png)
 #ifdef MOZ_SERVICES_SYNC
   skin/classic/browser/sync-16-throbber.png
   skin/classic/browser/sync-16.png
   skin/classic/browser/sync-24-throbber.png
   skin/classic/browser/sync-32.png
   skin/classic/browser/sync-bg.png
   skin/classic/browser/sync-128.png
   skin/classic/browser/sync-desktopIcon.png
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..87b0b855d2573ecca3a4d7ded942c63bd03521e4
GIT binary patch
literal 3217
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a5904654909b4767962fd68a5e4d926d3dab3aa8
GIT binary patch
literal 1237
zc$@*%1S<Q9P)<h;3K|Lk000e1NJLTq001Na000sQ1^@s6Gb4N`00001b5ch_0Itp)
z=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyb@
z3_3FC)$uj}00dP@L_t(Y$IX^&Y!p=#$A5QU_5m%sEzCFpnp(hul|&OFqCg-9g$i1s
ziIudVq96%rVnTx91M&eSX-FU@pixn`LeaK1wiXg%FeZ&cN-#kljoaD>WV=h--KC}7
zK6dB&Vejg&U)&l#c$3N8nYsUS&;NhUoO9uSHiV`db|4#YtGg{ttO<+)VRh$0*l_?k
z>o=CIE8VpDiMjI&Y|~+LyRX-5ZEpPSTuak=fYO&XKev8k*|NFw3LZkF>5#;{eXDok
zTuW1X>-UX63Qadky!Ag+xILZ$A#CG-Ojlhg&5Up;G`p(&#X5l6hStiy-tK7a=O0gY
z+_*LfO#O=uXYrDf{K_|Xx#kxXW>#(~t#ttTp1iy;FabD)z@8Q{Nn8jqp|JS?ZjWcA
zdgnG78X9Z^hJXwp7jUG&W58WtyyM2TydxjHztUUZ5(DxbfJ+DwYy0^^{+Ze@+}&Ni
z;dGc47A?$qwet1wv#ZyR04@L_Y_ZVLU>9%&aPB{NxP0026$>OxT9g+8T<sTs={$5`
zUp>$p8XDAuuoVF=hhi&E9IbIgBH?DhPr`r`$Vp)sRm@}ET|VQ)(V8{StXeBln2)F=
zoq6cMKHrv#Dt-G~yZfb-;|Xs>#+RQSf4HH}>jUCy?TErAHWC6EiG;5Mmw~Zhz;9~0
zk-P7}p;b?<SXn5goB(MGVaqIge%04NC*Y4n!gGYcummy=n8AQwYPvB7bT-s^^@;K5
z(w%$W^#OeH(UC`5n(D7A8)Is%sjws!iUY&IXfWVUN-GZ^+~4=|mWtVL?Ap@<ObH=o
z0(vmu@6dE(6d0Bg&5~EK<UAPg$28sO2ijVi>Jc{ELICAV8_*vN_+zQqWGJSR%u?i^
zG|jkE2&9xqC9z9wsF>ZCZ};V%)v4yjZ-VNzFVz_<)?wNF@1g023oxp7?0WK*@~s1P
z-jfA)f`RPnz59Do*IJ(wp=F+?8zm`g?7%%W_W-$?Zdkw1Q&{DYlv5UG?0~Ut$2%{S
zl~)XZ_wA{iI`7FbDa}#0$KwD(DgXbJWqz-r^+KKyV)b+itdug2ltcgIP$CpIO*aJK
zT(@D<lCtvGCL7Mw&N%(mXCW!gi$JXYv^NU~D#rz2lU9Y0;|{0u=6~s75}9KOnVgvA
zcF&50!<j(*{MqI^p`iioO8cc@(=^+GTdL<cEFsGB<mJr*IcZHyX;o}mDkbdNfM{QD
zkA3U*x3#S7?5BZZAnWp_Uqhy84yanRNWEVG6l=P%G%GuMc}3L@t*^JouIf{?`%mAD
zL`#wJ>0E$N*r?ES<I%;BEnQQ+_q}NT94$*A>}g6IAG{MBJ67{y=FRI@e*#!kykx`f
z>b-r1MGNnOOtU8n(cR_CJ$|fa{vRDT&I(O8a)HH)eTMqA(;0SPTot%v-jo23t0TyC
zjvry*ci>v`Jd_E{R5eDVorj4QGonJqgRt`#mb)4)8RTK500000NkvXXu0mjfw*E~O
new file mode 100644
--- /dev/null
+++ b/browser/themes/pinstripe/devtools/layoutview.css
@@ -0,0 +1,88 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is LayoutView.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2012
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Paul Rouget <paul@mozilla.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+body {
+  background: url(layout-background.png), -moz-radial-gradient(50% 70%, circle cover, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%);
+  color: hsl(210,100%,85%);
+  border-top: 1px solid black;
+  -moz-box-sizing: border-box;
+}
+
+#element-size {
+  color: hsl(210,100%,95%);
+}
+
+#main {
+  border-color: hsla(210,100%,85%,0.7);
+  border-style: dotted;
+}
+
+#main > .border {
+  color: hsl(210,53%,45%);
+}
+
+.border > span {
+  background-color: hsl(210,100%,85%);
+  border-radius: 2px;
+  padding: 0 4px;
+}
+
+#content {
+  border-color: hsla(210,100%,85%,0.7);
+  border-style: dotted 
+}
+
+#padding {
+  border-color: hsla(210,100%,85%,0.2);
+  border-style: solid;
+}
+
+#borders {
+  border-style: solid;
+  border-color: hsl(210,100%,85%);
+}
+
+#togglebutton {
+  background-image: url(layout-buttons.png);
+  width: 18px;
+  height: 18px;
+  margin-top: -3px;
+}
+
+body.open > #header > #togglebutton {
+  background-position: -18px 0;
+}
+
--- a/browser/themes/pinstripe/jar.mn
+++ b/browser/themes/pinstripe/jar.mn
@@ -174,16 +174,19 @@ browser.jar:
   skin/classic/browser/devtools/magnifying-glass.png        (devtools/magnifying-glass.png)
   skin/classic/browser/devtools/itemToggle.png              (devtools/itemToggle.png)
   skin/classic/browser/devtools/itemArrow-rtl.png           (devtools/itemArrow-rtl.png)
   skin/classic/browser/devtools/itemArrow-ltr.png           (devtools/itemArrow-ltr.png)
   skin/classic/browser/devtools/background-noise-toolbar.png (devtools/background-noise-toolbar.png)
   skin/classic/browser/devtools/inspect-button.png          (devtools/inspect-button.png)
   skin/classic/browser/devtools/dropmarker.png              (devtools/dropmarker.png)
   skin/classic/browser/devtools/treepanel-button.png        (devtools/treepanel-button.png)
+  skin/classic/browser/devtools/layout-background.png       (devtools/layout-background.png)
+  skin/classic/browser/devtools/layoutview.css              (devtools/layoutview.css)
+  skin/classic/browser/devtools/layout-buttons.png          (devtools/layout-buttons.png)
 #ifdef MOZ_SERVICES_SYNC
   skin/classic/browser/sync-throbber.png
   skin/classic/browser/sync-16.png
   skin/classic/browser/sync-32.png
   skin/classic/browser/sync-bg.png
   skin/classic/browser/sync-128.png
   skin/classic/browser/sync-desktopIcon.png
   skin/classic/browser/sync-mobileIcon.png
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..87b0b855d2573ecca3a4d7ded942c63bd03521e4
GIT binary patch
literal 3217
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a5904654909b4767962fd68a5e4d926d3dab3aa8
GIT binary patch
literal 1237
zc$@*%1S<Q9P)<h;3K|Lk000e1NJLTq001Na000sQ1^@s6Gb4N`00001b5ch_0Itp)
z=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyb@
z3_3FC)$uj}00dP@L_t(Y$IX^&Y!p=#$A5QU_5m%sEzCFpnp(hul|&OFqCg-9g$i1s
ziIudVq96%rVnTx91M&eSX-FU@pixn`LeaK1wiXg%FeZ&cN-#kljoaD>WV=h--KC}7
zK6dB&Vejg&U)&l#c$3N8nYsUS&;NhUoO9uSHiV`db|4#YtGg{ttO<+)VRh$0*l_?k
z>o=CIE8VpDiMjI&Y|~+LyRX-5ZEpPSTuak=fYO&XKev8k*|NFw3LZkF>5#;{eXDok
zTuW1X>-UX63Qadky!Ag+xILZ$A#CG-Ojlhg&5Up;G`p(&#X5l6hStiy-tK7a=O0gY
z+_*LfO#O=uXYrDf{K_|Xx#kxXW>#(~t#ttTp1iy;FabD)z@8Q{Nn8jqp|JS?ZjWcA
zdgnG78X9Z^hJXwp7jUG&W58WtyyM2TydxjHztUUZ5(DxbfJ+DwYy0^^{+Ze@+}&Ni
z;dGc47A?$qwet1wv#ZyR04@L_Y_ZVLU>9%&aPB{NxP0026$>OxT9g+8T<sTs={$5`
zUp>$p8XDAuuoVF=hhi&E9IbIgBH?DhPr`r`$Vp)sRm@}ET|VQ)(V8{StXeBln2)F=
zoq6cMKHrv#Dt-G~yZfb-;|Xs>#+RQSf4HH}>jUCy?TErAHWC6EiG;5Mmw~Zhz;9~0
zk-P7}p;b?<SXn5goB(MGVaqIge%04NC*Y4n!gGYcummy=n8AQwYPvB7bT-s^^@;K5
z(w%$W^#OeH(UC`5n(D7A8)Is%sjws!iUY&IXfWVUN-GZ^+~4=|mWtVL?Ap@<ObH=o
z0(vmu@6dE(6d0Bg&5~EK<UAPg$28sO2ijVi>Jc{ELICAV8_*vN_+zQqWGJSR%u?i^
zG|jkE2&9xqC9z9wsF>ZCZ};V%)v4yjZ-VNzFVz_<)?wNF@1g023oxp7?0WK*@~s1P
z-jfA)f`RPnz59Do*IJ(wp=F+?8zm`g?7%%W_W-$?Zdkw1Q&{DYlv5UG?0~Ut$2%{S
zl~)XZ_wA{iI`7FbDa}#0$KwD(DgXbJWqz-r^+KKyV)b+itdug2ltcgIP$CpIO*aJK
zT(@D<lCtvGCL7Mw&N%(mXCW!gi$JXYv^NU~D#rz2lU9Y0;|{0u=6~s75}9KOnVgvA
zcF&50!<j(*{MqI^p`iioO8cc@(=^+GTdL<cEFsGB<mJr*IcZHyX;o}mDkbdNfM{QD
zkA3U*x3#S7?5BZZAnWp_Uqhy84yanRNWEVG6l=P%G%GuMc}3L@t*^JouIf{?`%mAD
zL`#wJ>0E$N*r?ES<I%;BEnQQ+_q}NT94$*A>}g6IAG{MBJ67{y=FRI@e*#!kykx`f
z>b-r1MGNnOOtU8n(cR_CJ$|fa{vRDT&I(O8a)HH)eTMqA(;0SPTot%v-jo23t0TyC
zjvry*ci>v`Jd_E{R5eDVorj4QGonJqgRt`#mb)4)8RTK500000NkvXXu0mjfw*E~O
new file mode 100644
--- /dev/null
+++ b/browser/themes/winstripe/devtools/layoutview.css
@@ -0,0 +1,88 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is LayoutView.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2012
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Paul Rouget <paul@mozilla.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+body {
+  background: url(layout-background.png), -moz-radial-gradient(50% 70%, circle cover, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%);
+  color: hsl(210,100%,85%);
+  border-top: 1px solid black;
+  -moz-box-sizing: border-box;
+}
+
+#element-size {
+  color: hsl(210,100%,95%);
+}
+
+#main {
+  border-color: hsla(210,100%,85%,0.7);
+  border-style: dotted;
+}
+
+#main > .border {
+  color: hsl(210,53%,45%);
+}
+
+.border > span {
+  background-color: hsl(210,100%,85%);
+  border-radius: 2px;
+  padding: 0 4px;
+}
+
+#content {
+  border-color: hsla(210,100%,85%,0.7);
+  border-style: dotted 
+}
+
+#padding {
+  border-color: hsla(210,100%,85%,0.2);
+  border-style: solid;
+}
+
+#borders {
+  border-style: solid;
+  border-color: hsl(210,100%,85%);
+}
+
+#togglebutton {
+  background-image: url(layout-buttons.png);
+  width: 18px;
+  height: 18px;
+  margin-top: -3px;
+}
+
+body.open > #header > #togglebutton {
+  background-position: -18px 0;
+}
+
--- a/browser/themes/winstripe/jar.mn
+++ b/browser/themes/winstripe/jar.mn
@@ -160,16 +160,19 @@ browser.jar:
         skin/classic/browser/devtools/debugger.css                  (devtools/debugger.css)
         skin/classic/browser/devtools/magnifying-glass.png          (devtools/magnifying-glass.png)
         skin/classic/browser/devtools/itemToggle.png                (devtools/itemToggle.png)
         skin/classic/browser/devtools/itemArrow-rtl.png             (devtools/itemArrow-rtl.png)
         skin/classic/browser/devtools/itemArrow-ltr.png             (devtools/itemArrow-ltr.png)
         skin/classic/browser/devtools/inspect-button.png            (devtools/inspect-button.png)
         skin/classic/browser/devtools/dropmarker.png                (devtools/dropmarker.png)
         skin/classic/browser/devtools/treepanel-button.png          (devtools/treepanel-button.png)
+        skin/classic/browser/devtools/layout-background.png         (devtools/layout-background.png)
+        skin/classic/browser/devtools/layoutview.css                (devtools/layoutview.css)
+        skin/classic/browser/devtools/layout-buttons.png            (devtools/layout-buttons.png)
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/browser/sync-throbber.png
         skin/classic/browser/sync-16.png
         skin/classic/browser/sync-32.png
         skin/classic/browser/sync-128.png
         skin/classic/browser/sync-bg.png
         skin/classic/browser/sync-desktopIcon.png
         skin/classic/browser/sync-mobileIcon.png
@@ -340,16 +343,19 @@ browser.jar:
         skin/classic/aero/browser/devtools/debugger.css              (devtools/debugger.css)
         skin/classic/aero/browser/devtools/magnifying-glass.png      (devtools/magnifying-glass.png)
         skin/classic/aero/browser/devtools/itemToggle.png            (devtools/itemToggle.png)
         skin/classic/aero/browser/devtools/itemArrow-rtl.png         (devtools/itemArrow-rtl.png)
         skin/classic/aero/browser/devtools/itemArrow-ltr.png         (devtools/itemArrow-ltr.png)
         skin/classic/aero/browser/devtools/inspect-button.png        (devtools/inspect-button.png)
         skin/classic/aero/browser/devtools/dropmarker.png            (devtools/dropmarker.png)
         skin/classic/aero/browser/devtools/treepanel-button.png      (devtools/treepanel-button.png)
+        skin/classic/aero/browser/devtools/layout-background.png     (devtools/layout-background.png)
+        skin/classic/aero/browser/devtools/layoutview.css            (devtools/layoutview.css)
+        skin/classic/aero/browser/devtools/layout-buttons.png        (devtools/layout-buttons.png)
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/aero/browser/sync-throbber.png
         skin/classic/aero/browser/sync-16.png
         skin/classic/aero/browser/sync-32.png
         skin/classic/aero/browser/sync-128.png
         skin/classic/aero/browser/sync-bg.png
         skin/classic/aero/browser/sync-desktopIcon.png
         skin/classic/aero/browser/sync-mobileIcon.png