Bug 1336198 - Part 8: Use the react/redux box model in the computed view. r=jdescottes
☠☠ backed out by dbf5e2d59850 ☠ ☠
authorGabriel Luong <gabriel.luong@gmail.com>
Sun, 19 Feb 2017 22:52:05 -0500
changeset 372862 b2d689c41408b6e59660552f9cd2eb3ee03ff558
parent 372861 29efd4e3acf025dec21a0ead931379f288e0849d
child 372863 148f39b53d9cdceaf32f1474b6bb7369f7cb1ea3
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes
bugs1336198
milestone54.0a1
Bug 1336198 - Part 8: Use the react/redux box model in the computed view. r=jdescottes
devtools/client/inspector/boxmodel/box-model.js
devtools/client/inspector/boxmodel/components/BoxModelApp.js
devtools/client/inspector/boxmodel/components/moz.build
devtools/client/inspector/computed/computed.js
devtools/client/inspector/inspector.js
devtools/client/shared/browser-loader.js
--- a/devtools/client/inspector/boxmodel/box-model.js
+++ b/devtools/client/inspector/boxmodel/box-model.js
@@ -70,22 +70,23 @@ BoxModel.prototype = {
     return {
       onHideBoxModelHighlighter: this.onHideBoxModelHighlighter,
       onShowBoxModelEditor: this.onShowBoxModelEditor,
       onShowBoxModelHighlighter: this.onShowBoxModelHighlighter,
     };
   },
 
   /**
-   * Returns true if the layout panel is visible, and false otherwise.
+   * Returns true if the computed or layout panel is visible, and false otherwise.
    */
   isPanelVisible() {
     return this.inspector.toolbox.currentToolId === "inspector" &&
            this.inspector.sidebar &&
-           this.inspector.sidebar.getCurrentTabID() === "layoutview";
+           (this.inspector.sidebar.getCurrentTabID() === "layoutview" ||
+            this.inspector.sidebar.getCurrentTabID() === "computedview");
   },
 
   /**
    * Returns true if the layout panel is visible and the current node is valid to
    * be displayed in the view.
    */
   isPanelVisibleAndNodeValid() {
     return this.isPanelVisible() &&
@@ -162,16 +163,21 @@ BoxModel.prototype = {
   /**
    * Selection 'new-node-front' event handler.
    */
   onNewSelection: function () {
     if (!this.isPanelVisibleAndNodeValid()) {
       return;
     }
 
+    if (this.inspector.selection.isConnected() &&
+        this.inspector.selection.isElementNode()) {
+      this.trackReflows();
+    }
+
     this.updateBoxModel();
   },
 
   /**
    * Hides the box-model highlighter on the currently selected element.
    */
   onHideBoxModelHighlighter() {
     let toolbox = this.inspector.toolbox;
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/boxmodel/components/BoxModelApp.js
@@ -0,0 +1,51 @@
+/* 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/. */
+
+"use strict";
+
+const { addons, createClass, createFactory, PropTypes } =
+  require("devtools/client/shared/vendor/react");
+const { connect } = require("devtools/client/shared/vendor/react-redux");
+
+const { LocalizationHelper } = require("devtools/shared/l10n");
+
+const Accordion =
+  createFactory(require("devtools/client/inspector/layout/components/Accordion"));
+const BoxModel = createFactory(require("./BoxModel"));
+
+const Types = require("../types");
+
+const BOXMODEL_STRINGS_URI = "devtools/client/locales/boxmodel.properties";
+const BOXMODEL_L10N = new LocalizationHelper(BOXMODEL_STRINGS_URI);
+
+const BoxModelApp = createClass({
+
+  displayName: "BoxModelApp",
+
+  propTypes: {
+    boxModel: PropTypes.shape(Types.boxModel).isRequired,
+    showBoxModelProperties: PropTypes.bool.isRequired,
+    onHideBoxModelHighlighter: PropTypes.func.isRequired,
+    onShowBoxModelEditor: PropTypes.func.isRequired,
+    onShowBoxModelHighlighter: PropTypes.func.isRequired,
+  },
+
+  mixins: [ addons.PureRenderMixin ],
+
+  render() {
+    return Accordion({
+      items: [
+        {
+          header: BOXMODEL_L10N.getStr("boxmodel.title"),
+          component: BoxModel,
+          componentProps: this.props,
+          opened: true,
+        }
+      ]
+    });
+  },
+
+});
+
+module.exports = connect(state => state)(BoxModelApp);
--- a/devtools/client/inspector/boxmodel/components/moz.build
+++ b/devtools/client/inspector/boxmodel/components/moz.build
@@ -1,14 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DevToolsModules(
     'BoxModel.js',
+    'BoxModelApp.js',
     'BoxModelEditable.js',
     'BoxModelInfo.js',
     'BoxModelMain.js',
     'BoxModelProperties.js',
     'ComputedProperty.js',
 )
--- a/devtools/client/inspector/computed/computed.js
+++ b/devtools/client/inspector/computed/computed.js
@@ -23,16 +23,22 @@ const {
   VIEW_NODE_VALUE_TYPE,
   VIEW_NODE_IMAGE_URL_TYPE,
 } = require("devtools/client/inspector/shared/node-types");
 const StyleInspectorMenu = require("devtools/client/inspector/shared/style-inspector-menu");
 const TooltipsOverlay = require("devtools/client/inspector/shared/tooltips-overlay");
 const KeyShortcuts = require("devtools/client/shared/key-shortcuts");
 const clipboardHelper = require("devtools/shared/platform/clipboard");
 
+const { createElement, createFactory } = require("devtools/client/shared/vendor/react");
+const ReactDOM = require("devtools/client/shared/vendor/react-dom");
+const { Provider } = require("devtools/client/shared/vendor/react-redux");
+
+const BoxModelApp = createFactory(require("devtools/client/inspector/boxmodel/components/BoxModelApp"));
+
 const STYLE_INSPECTOR_PROPERTIES = "devtools/shared/locales/styleinspector.properties";
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const STYLE_INSPECTOR_L10N = new LocalizationHelper(STYLE_INSPECTOR_PROPERTIES);
 
 const PREF_ORIG_SOURCES = "devtools.styleeditor.source-maps-enabled";
 
 const FILTER_CHANGED_TIMEOUT = 150;
 const HTML_NS = "http://www.w3.org/1999/xhtml";
@@ -148,16 +154,17 @@ UpdateProcess.prototype = {
  *        The document that will contain the computed view.
  * @param {PageStyleFront} pageStyle
  *        Front for the page style actor that will be providing
  *        the style information.
  */
 function CssComputedView(inspector, document, pageStyle) {
   this.inspector = inspector;
   this.highlighters = inspector.highlighters;
+  this.store = inspector.store;
   this.styleDocument = document;
   this.styleWindow = this.styleDocument.defaultView;
   this.pageStyle = pageStyle;
 
   this.propertyViews = [];
 
   let cssProperties = getCssProperties(inspector.toolbox);
   this._outputParser = new OutputParser(document, cssProperties);
@@ -203,16 +210,17 @@ function CssComputedView(inspector, docu
   this._onSourcePrefChanged = this._onSourcePrefChanged.bind(this);
   this._prefObserver = new PrefObserver("devtools.");
   this._prefObserver.on(PREF_ORIG_SOURCES, this._onSourcePrefChanged);
   this._prefObserver.on("devtools.defaultColorUnit", this._handlePrefChange);
 
   // The element that we're inspecting, and the document that it comes from.
   this._viewedElement = null;
 
+  this.createBoxModelView();
   this.createStyleViews();
 
   this._contextmenu = new StyleInspectorMenu(this, { isRuleView: false });
 
   // Add the tooltips and highlightersoverlay
   this.tooltips = new TooltipsOverlay(this);
   this.tooltips.addToView();
 
@@ -600,16 +608,39 @@ CssComputedView.prototype = {
     this._handlePrefChange();
     for (let propView of this.propertyViews) {
       propView.updateSourceLinks();
     }
     this.inspector.emit("computed-view-sourcelinks-updated");
   },
 
   /**
+   * Render the box model view.
+   */
+  createBoxModelView: function () {
+    let {
+      onHideBoxModelHighlighter,
+      onShowBoxModelEditor,
+      onShowBoxModelHighlighter,
+    } = this.inspector.boxmodel.getComponentProps();
+
+    let provider = createElement(
+      Provider,
+      { store: this.store },
+      BoxModelApp({
+        showBoxModelProperties: false,
+        onHideBoxModelHighlighter,
+        onShowBoxModelEditor,
+        onShowBoxModelHighlighter,
+      })
+    );
+    ReactDOM.render(provider, this.styleDocument.getElementById("boxmodel-wrapper"));
+  },
+
+  /**
    * The CSS as displayed by the UI.
    */
   createStyleViews: function () {
     if (CssComputedView.propertyNames) {
       return;
     }
 
     CssComputedView.propertyNames = [];
@@ -790,16 +821,17 @@ CssComputedView.prototype = {
     // Property views
     for (let propView of this.propertyViews) {
       propView.destroy();
     }
     this.propertyViews = null;
 
     this.inspector = null;
     this.highlighters = null;
+    this.store = null;
     this.styleDocument = null;
     this.styleWindow = null;
 
     this._isDestroyed = true;
   }
 };
 
 function PropertyInfo(tree, name) {
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -19,17 +19,16 @@ const {initCssProperties} = require("dev
 const nodeConstants = require("devtools/shared/dom-node-constants");
 const Telemetry = require("devtools/client/shared/telemetry");
 
 const Menu = require("devtools/client/framework/menu");
 const MenuItem = require("devtools/client/framework/menu-item");
 
 const {HTMLBreadcrumbs} = require("devtools/client/inspector/breadcrumbs");
 const BoxModel = require("devtools/client/inspector/boxmodel/box-model");
-const {ComputedViewTool} = require("devtools/client/inspector/computed/computed");
 const {FontInspector} = require("devtools/client/inspector/fonts/fonts");
 const {InspectorSearch} = require("devtools/client/inspector/inspector-search");
 const {RuleViewTool} = require("devtools/client/inspector/rules/rules");
 const HighlightersOverlay = require("devtools/client/inspector/shared/highlighters-overlay");
 const {ToolSidebar} = require("devtools/client/inspector/toolsidebar");
 const MarkupView = require("devtools/client/inspector/markup/markup");
 const {CommandUtils} = require("devtools/client/shared/developer-toolbar");
 const {ViewHelpers} = require("devtools/client/shared/widgets/view-helpers");
@@ -568,18 +567,21 @@ Inspector.prototype = {
       defaultTab == "ruleview");
 
     this.sidebar.addExistingTab(
       "computedview",
       INSPECTOR_L10N.getStr("inspector.sidebar.computedViewTitle"),
       defaultTab == "computedview");
 
     this.ruleview = new RuleViewTool(this, this.panelWin);
+    this.boxmodel = new BoxModel(this, this.panelWin);
+
+    const {ComputedViewTool} =
+      this.browserRequire("devtools/client/inspector/computed/computed");
     this.computedview = new ComputedViewTool(this, this.panelWin);
-    this.boxmodel = new BoxModel(this, this.panelWin);
 
     if (Services.prefs.getBoolPref("devtools.layoutview.enabled")) {
       const LayoutView = this.browserRequire("devtools/client/inspector/layout/layout");
       this.layoutview = new LayoutView(this, this.panelWin);
     }
 
     if (this.target.form.animationsActor) {
       this.sidebar.addFrameTab(
--- a/devtools/client/shared/browser-loader.js
+++ b/devtools/client/shared/browser-loader.js
@@ -8,16 +8,17 @@ const loaders = Cu.import("resource://gr
 const { devtools } = Cu.import("resource://devtools/shared/Loader.jsm", {});
 const { joinURI } = devtools.require("devtools/shared/path");
 const { assert } = devtools.require("devtools/shared/DevToolsUtils");
 const Services = devtools.require("Services");
 const { AppConstants } = devtools.require("resource://gre/modules/AppConstants.jsm");
 
 const BROWSER_BASED_DIRS = [
   "resource://devtools/client/inspector/boxmodel",
+  "resource://devtools/client/inspector/computed",
   "resource://devtools/client/inspector/layout",
   "resource://devtools/client/jsonview",
   "resource://devtools/client/shared/vendor",
   "resource://devtools/client/shared/redux",
 ];
 
 const COMMON_LIBRARY_DIRS = [
   "resource://devtools/client/shared/vendor",