Bug 1342305 - Refactor grid inspector into its own grids folder. r=jdescottes
authorGabriel Luong <gabriel.luong@gmail.com>
Fri, 24 Feb 2017 14:14:04 -0500
changeset 345214 417a8c548d3944bd91eb26322f2092525f727ff4
parent 345213 0a15dfecc9fa2b375e5de3ad6f195516b1de2d2f
child 345215 2e920e33d89acdbaed9b54e439efa99c5f68b557
push id87535
push usergabriel.luong@gmail.com
push dateWed, 01 Mar 2017 07:37:22 +0000
treeherdermozilla-inbound@417a8c548d39 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes
bugs1342305
milestone54.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 1342305 - Refactor grid inspector into its own grids folder. r=jdescottes
devtools/client/inspector/grids/actions/grids.js
devtools/client/inspector/grids/actions/highlighter-settings.js
devtools/client/inspector/grids/actions/index.js
devtools/client/inspector/grids/actions/moz.build
devtools/client/inspector/grids/components/Grid.js
devtools/client/inspector/grids/components/GridDisplaySettings.js
devtools/client/inspector/grids/components/GridItem.js
devtools/client/inspector/grids/components/GridList.js
devtools/client/inspector/grids/components/GridOutline.js
devtools/client/inspector/grids/components/moz.build
devtools/client/inspector/grids/grid-inspector.js
devtools/client/inspector/grids/moz.build
devtools/client/inspector/grids/reducers/grids.js
devtools/client/inspector/grids/reducers/highlighter-settings.js
devtools/client/inspector/grids/reducers/moz.build
devtools/client/inspector/grids/types.js
devtools/client/inspector/grids/utils/l10n.js
devtools/client/inspector/grids/utils/moz.build
devtools/client/inspector/inspector.js
devtools/client/inspector/layout/actions/grids.js
devtools/client/inspector/layout/actions/highlighter-settings.js
devtools/client/inspector/layout/actions/index.js
devtools/client/inspector/layout/actions/moz.build
devtools/client/inspector/layout/components/App.js
devtools/client/inspector/layout/components/Grid.js
devtools/client/inspector/layout/components/GridDisplaySettings.js
devtools/client/inspector/layout/components/GridItem.js
devtools/client/inspector/layout/components/GridList.js
devtools/client/inspector/layout/components/GridOutline.js
devtools/client/inspector/layout/components/moz.build
devtools/client/inspector/layout/layout.js
devtools/client/inspector/layout/moz.build
devtools/client/inspector/layout/reducers/grids.js
devtools/client/inspector/layout/reducers/highlighter-settings.js
devtools/client/inspector/layout/reducers/moz.build
devtools/client/inspector/layout/types.js
devtools/client/inspector/layout/utils/l10n.js
devtools/client/inspector/layout/utils/moz.build
devtools/client/inspector/moz.build
devtools/client/inspector/reducers.js
devtools/client/shared/browser-loader.js
rename from devtools/client/inspector/layout/actions/grids.js
rename to devtools/client/inspector/grids/actions/grids.js
rename from devtools/client/inspector/layout/actions/highlighter-settings.js
rename to devtools/client/inspector/grids/actions/highlighter-settings.js
rename from devtools/client/inspector/layout/actions/index.js
rename to devtools/client/inspector/grids/actions/index.js
rename from devtools/client/inspector/layout/actions/moz.build
rename to devtools/client/inspector/grids/actions/moz.build
rename from devtools/client/inspector/layout/components/Grid.js
rename to devtools/client/inspector/grids/components/Grid.js
rename from devtools/client/inspector/layout/components/GridDisplaySettings.js
rename to devtools/client/inspector/grids/components/GridDisplaySettings.js
rename from devtools/client/inspector/layout/components/GridItem.js
rename to devtools/client/inspector/grids/components/GridItem.js
rename from devtools/client/inspector/layout/components/GridList.js
rename to devtools/client/inspector/grids/components/GridList.js
rename from devtools/client/inspector/layout/components/GridOutline.js
rename to devtools/client/inspector/grids/components/GridOutline.js
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/grids/components/moz.build
@@ -0,0 +1,13 @@
+# -*- 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(
+    'Grid.js',
+    'GridDisplaySettings.js',
+    'GridItem.js',
+    'GridList.js',
+    'GridOutline.js',
+)
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/grids/grid-inspector.js
@@ -0,0 +1,404 @@
+/* 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 Services = require("Services");
+const { Task } = require("devtools/shared/task");
+
+const SwatchColorPickerTooltip = require("devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip");
+
+const {
+  updateGridColor,
+  updateGridHighlighted,
+  updateGrids,
+} = require("./actions/grids");
+const {
+  updateShowGridLineNumbers,
+  updateShowInfiniteLines,
+} = require("./actions/highlighter-settings");
+
+const SHOW_GRID_LINE_NUMBERS = "devtools.gridinspector.showGridLineNumbers";
+const SHOW_INFINITE_LINES_PREF = "devtools.gridinspector.showInfiniteLines";
+
+// Default grid colors.
+const GRID_COLORS = [
+  "#05E4EE",
+  "#BB9DFF",
+  "#FFB53B",
+  "#71F362",
+  "#FF90FF",
+  "#FF90FF",
+  "#1B80FF",
+  "#FF2647"
+];
+
+function GridInspector(inspector, window) {
+  this.document = window.document;
+  this.highlighters = inspector.highlighters;
+  this.inspector = inspector;
+  this.store = inspector.store;
+  this.walker = this.inspector.walker;
+
+  this.getSwatchColorPickerTooltip = this.getSwatchColorPickerTooltip.bind(this);
+  this.setSelectedNode = this.setSelectedNode.bind(this);
+  this.updateGridPanel = this.updateGridPanel.bind(this);
+
+  this.onGridLayoutChange = this.onGridLayoutChange.bind(this);
+  this.onHighlighterChange = this.onHighlighterChange.bind(this);
+  this.onSetGridOverlayColor = this.onSetGridOverlayColor.bind(this);
+  this.onShowBoxModelHighlighterForNode =
+    this.onShowBoxModelHighlighterForNode.bind(this);
+  this.onShowGridAreaHighlight = this.onShowGridAreaHighlight.bind(this);
+  this.onSidebarSelect = this.onSidebarSelect.bind(this);
+  this.onToggleGridHighlighter = this.onToggleGridHighlighter.bind(this);
+  this.onToggleShowGridLineNumbers = this.onToggleShowGridLineNumbers.bind(this);
+  this.onToggleShowInfiniteLines = this.onToggleShowInfiniteLines.bind(this);
+
+  this.init();
+}
+
+GridInspector.prototype = {
+
+  /**
+   * Initializes the grid inspector by fetching the LayoutFront from the walker, loading
+   * the highlighter settings and initalizing the SwatchColorPicker instance.
+   */
+  init: Task.async(function* () {
+    if (!this.inspector) {
+      return;
+    }
+
+    this.layoutInspector = yield this.inspector.walker.getLayoutInspector();
+
+    this.loadHighlighterSettings();
+
+    // Create a shared SwatchColorPicker instance to be reused by all GridItem components.
+    this.swatchColorPickerTooltip = new SwatchColorPickerTooltip(
+      this.inspector.toolbox.doc,
+      this.inspector,
+      {
+        supportsCssColor4ColorFunction: () => false
+      }
+    );
+
+    this.highlighters.on("grid-highlighter-hidden", this.onHighlighterChange);
+    this.highlighters.on("grid-highlighter-shown", this.onHighlighterChange);
+    this.inspector.sidebar.on("select", this.onSidebarSelect);
+
+    this.onSidebarSelect();
+  }),
+
+  /**
+   * Destruction function called when the inspector is destroyed. Removes event listeners
+   * and cleans up references.
+   */
+  destroy() {
+    this.highlighters.off("grid-highlighter-hidden", this.onHighlighterChange);
+    this.highlighters.off("grid-highlighter-shown", this.onHighlighterChange);
+    this.inspector.sidebar.off("select", this.onSidebarSelect);
+    this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
+
+    this.swatchColorPickerTooltip.destroy();
+
+    this.document = null;
+    this.highlighters = null;
+    this.inspector = null;
+    this.layoutInspector = null;
+    this.store = null;
+    this.swatchColorPickerTooltip = null;
+    this.walker = null;
+  },
+
+  getComponentProps() {
+    return {
+      getSwatchColorPickerTooltip: this.getSwatchColorPickerTooltip,
+      setSelectedNode: this.setSelectedNode,
+      onSetGridOverlayColor: this.onSetGridOverlayColor,
+      onShowBoxModelHighlighterForNode: this.onShowBoxModelHighlighterForNode,
+      onShowGridAreaHighlight: this.onShowGridAreaHighlight,
+      onToggleGridHighlighter: this.onToggleGridHighlighter,
+      onToggleShowGridLineNumbers: this.onToggleShowGridLineNumbers,
+      onToggleShowInfiniteLines: this.onToggleShowInfiniteLines,
+    };
+  },
+
+  /**
+   * Returns the color set for the grid highlighter associated with the provided
+   * nodeFront.
+   *
+   * @param  {NodeFront} nodeFront
+   *         The NodeFront for which we need the color.
+   */
+  getGridColorForNodeFront(nodeFront) {
+    let { grids } = this.store.getState();
+
+    for (let grid of grids) {
+      if (grid.nodeFront === nodeFront) {
+        return grid.color;
+      }
+    }
+
+    return null;
+  },
+
+  /**
+   * Create a highlighter settings object for the provided nodeFront.
+   *
+   * @param  {NodeFront} nodeFront
+   *         The NodeFront for which we need highlighter settings.
+   */
+  getGridHighlighterSettings(nodeFront) {
+    let { highlighterSettings } = this.store.getState();
+
+    // Get the grid color for the provided nodeFront.
+    let color = this.getGridColorForNodeFront(nodeFront);
+
+    // Merge the grid color to the generic highlighter settings.
+    return Object.assign({}, highlighterSettings, {
+      color
+    });
+  },
+
+  /**
+   * Retrieve the shared SwatchColorPicker instance.
+   */
+  getSwatchColorPickerTooltip() {
+    return this.swatchColorPickerTooltip;
+  },
+
+  /**
+   * Returns true if the layout panel is visible, and false otherwise.
+   */
+  isPanelVisible() {
+    return this.inspector.toolbox.currentToolId === "inspector" &&
+           this.inspector.sidebar &&
+           this.inspector.sidebar.getCurrentTabID() === "layoutview";
+  },
+
+  /**
+   * Load the grid highligher display settings into the store from the stored preferences.
+   */
+  loadHighlighterSettings() {
+    let { dispatch } = this.store;
+
+    let showGridLineNumbers = Services.prefs.getBoolPref(SHOW_GRID_LINE_NUMBERS);
+    let showInfinteLines = Services.prefs.getBoolPref(SHOW_INFINITE_LINES_PREF);
+
+    dispatch(updateShowGridLineNumbers(showGridLineNumbers));
+    dispatch(updateShowInfiniteLines(showInfinteLines));
+  },
+
+  /**
+   * Set the inspector selection.
+   *
+   * @param {NodeFront} nodeFront
+   *        The NodeFront corresponding to the new selection.
+   */
+  setSelectedNode(nodeFront) {
+    this.inspector.selection.setNodeFront(nodeFront, "layout-panel");
+  },
+
+  /**
+   * Updates the grid panel by dispatching the new grid data. This is called when the
+   * layout view becomes visible or the view needs to be updated with new grid data.
+   *
+   * @param  {Array|null} gridFronts
+   *         Optional array of all GridFront in the current page.
+   */
+  updateGridPanel: Task.async(function* (gridFronts) {
+    // Stop refreshing if the inspector or store is already destroyed.
+    if (!this.inspector || !this.store) {
+      return;
+    }
+
+    // Get all the GridFront from the server if no gridFronts were provided.
+    if (!gridFronts) {
+      gridFronts = yield this.layoutInspector.getAllGrids(this.walker.rootNode);
+    }
+
+    let grids = [];
+    for (let i = 0; i < gridFronts.length; i++) {
+      let grid = gridFronts[i];
+      let nodeFront = yield this.walker.getNodeFromActor(grid.actorID, ["containerEl"]);
+
+      let fallbackColor = GRID_COLORS[i % GRID_COLORS.length];
+      let color = this.getGridColorForNodeFront(nodeFront) || fallbackColor;
+
+      grids.push({
+        id: i,
+        color,
+        gridFragments: grid.gridFragments,
+        highlighted: nodeFront == this.highlighters.gridHighlighterShown,
+        nodeFront,
+      });
+    }
+
+    this.store.dispatch(updateGrids(grids));
+  }),
+
+  /**
+   * Handler for "grid-layout-changed" events emitted from the LayoutActor.
+   *
+   * @param  {Array} grids
+   *         Array of all GridFront in the current page.
+   */
+  onGridLayoutChange(grids) {
+    if (this.isPanelVisible()) {
+      this.updateGridPanel(grids);
+    }
+  },
+
+  /**
+   * Handler for "grid-highlighter-shown" and "grid-highlighter-hidden" events emitted
+   * from the HighlightersOverlay. Updates the NodeFront's grid highlighted state.
+   *
+   * @param  {Event} event
+   *         Event that was triggered.
+   * @param  {NodeFront} nodeFront
+   *         The NodeFront of the grid container element for which the grid highlighter
+   *         is shown for.
+   */
+  onHighlighterChange(event, nodeFront) {
+    let highlighted = event === "grid-highlighter-shown";
+    this.store.dispatch(updateGridHighlighted(nodeFront, highlighted));
+  },
+
+  /**
+   * Handler for a change in the grid overlay color picker for a grid container.
+   *
+   * @param  {NodeFront} node
+   *         The NodeFront of the grid container element for which the grid color is
+   *         being updated.
+   * @param  {String} color
+   *         A hex string representing the color to use.
+   */
+  onSetGridOverlayColor(node, color) {
+    this.store.dispatch(updateGridColor(node, color));
+    let { grids } = this.store.getState();
+
+    // If the grid for which the color was updated currently has a highlighter, update
+    // the color.
+    for (let grid of grids) {
+      if (grid.nodeFront === node && grid.highlighted) {
+        let highlighterSettings = this.getGridHighlighterSettings(node);
+        this.highlighters.showGridHighlighter(node, highlighterSettings);
+      }
+    }
+  },
+
+  /**
+   * Shows the box-model highlighter on the element corresponding to the provided
+   * NodeFront.
+   *
+   * @param  {NodeFront} nodeFront
+   *         The node to highlight.
+   * @param  {Object} options
+   *         Options passed to the highlighter actor.
+   */
+  onShowBoxModelHighlighterForNode(nodeFront, options) {
+    let toolbox = this.inspector.toolbox;
+    toolbox.highlighterUtils.highlightNodeFront(nodeFront, options);
+  },
+
+  /**
+   * Highlights the grid area in the CSS Grid Highlighter for the given grid.
+   *
+   * @param  {NodeFront} node
+   *         The NodeFront of the grid container element for which the grid
+   *         highlighter is highlighted for.
+   * @param  {String} gridAreaName
+   *         The name of the grid area for which the grid highlighter
+   *         is highlighted for.
+   * @param  {String} color
+   *         The color of the grid area for which the grid highlighter
+   *         is highlighted for.
+   */
+  onShowGridAreaHighlight(node, gridAreaName, color) {
+    let { highlighterSettings } = this.store.getState();
+
+    highlighterSettings.showGridArea = gridAreaName;
+    highlighterSettings.color = color;
+
+    this.highlighters.showGridHighlighter(node, highlighterSettings);
+  },
+
+  /**
+   * Handler for the inspector sidebar select event. Starts listening for
+   * "grid-layout-changed" if the layout panel is visible. Otherwise, stop
+   * listening for grid layout changes. Finally, refresh the layout view if
+   * it is visible.
+   */
+  onSidebarSelect() {
+    if (!this.isPanelVisible()) {
+      this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
+      return;
+    }
+
+    this.layoutInspector.on("grid-layout-changed", this.onGridLayoutChange);
+    this.updateGridPanel();
+  },
+
+  /**
+   * Handler for a change in the input checkboxes in the GridList component.
+   * Toggles on/off the grid highlighter for the provided grid container element.
+   *
+   * @param  {NodeFront} node
+   *         The NodeFront of the grid container element for which the grid
+   *         highlighter is toggled on/off for.
+   */
+  onToggleGridHighlighter(node) {
+    let highlighterSettings = this.getGridHighlighterSettings(node);
+    this.highlighters.toggleGridHighlighter(node, highlighterSettings);
+  },
+
+  /**
+   * Handler for a change in the show grid line numbers checkbox in the
+   * GridDisplaySettings component. Toggles on/off the option to show the grid line
+   * numbers in the grid highlighter. Refreshes the shown grid highlighter for the
+   * grids currently highlighted.
+   *
+   * @param  {Boolean} enabled
+   *         Whether or not the grid highlighter should show the grid line numbers.
+   */
+  onToggleShowGridLineNumbers(enabled) {
+    this.store.dispatch(updateShowGridLineNumbers(enabled));
+    Services.prefs.setBoolPref(SHOW_GRID_LINE_NUMBERS, enabled);
+
+    let { grids } = this.store.getState();
+
+    for (let grid of grids) {
+      if (grid.highlighted) {
+        let highlighterSettings = this.getGridHighlighterSettings(grid.nodeFront);
+        this.highlighters.showGridHighlighter(grid.nodeFront, highlighterSettings);
+      }
+    }
+  },
+
+  /**
+   * Handler for a change in the extend grid lines infinitely checkbox in the
+   * GridDisplaySettings component. Toggles on/off the option to extend the grid
+   * lines infinitely in the grid highlighter. Refreshes the shown grid highlighter
+   * for grids currently highlighted.
+   *
+   * @param  {Boolean} enabled
+   *         Whether or not the grid highlighter should extend grid lines infinitely.
+   */
+  onToggleShowInfiniteLines(enabled) {
+    this.store.dispatch(updateShowInfiniteLines(enabled));
+    Services.prefs.setBoolPref(SHOW_INFINITE_LINES_PREF, enabled);
+
+    let { grids } = this.store.getState();
+
+    for (let grid of grids) {
+      if (grid.highlighted) {
+        let highlighterSettings = this.getGridHighlighterSettings(grid.nodeFront);
+        this.highlighters.showGridHighlighter(grid.nodeFront, highlighterSettings);
+      }
+    }
+  },
+
+};
+
+module.exports = GridInspector;
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/grids/moz.build
@@ -0,0 +1,17 @@
+# -*- 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/.
+
+DIRS += [
+    'actions',
+    'components',
+    'reducers',
+    'utils',
+]
+
+DevToolsModules(
+    'grid-inspector.js',
+    'types.js',
+)
rename from devtools/client/inspector/layout/reducers/grids.js
rename to devtools/client/inspector/grids/reducers/grids.js
rename from devtools/client/inspector/layout/reducers/highlighter-settings.js
rename to devtools/client/inspector/grids/reducers/highlighter-settings.js
rename from devtools/client/inspector/layout/reducers/moz.build
rename to devtools/client/inspector/grids/reducers/moz.build
rename from devtools/client/inspector/layout/types.js
rename to devtools/client/inspector/grids/types.js
rename from devtools/client/inspector/layout/utils/l10n.js
rename to devtools/client/inspector/grids/utils/l10n.js
rename from devtools/client/inspector/layout/utils/moz.build
rename to devtools/client/inspector/grids/utils/moz.build
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -20,16 +20,17 @@ const nodeConstants = require("devtools/
 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 {FontInspector} = require("devtools/client/inspector/fonts/fonts");
+const GridInspector = require("devtools/client/inspector/grids/grid-inspector");
 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");
 const clipboardHelper = require("devtools/shared/platform/clipboard");
@@ -572,16 +573,18 @@ Inspector.prototype = {
     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);
 
     if (Services.prefs.getBoolPref("devtools.layoutview.enabled")) {
+      this.gridInspector = new GridInspector(this, this.panelWin);
+
       const LayoutView = this.browserRequire("devtools/client/inspector/layout/layout");
       this.layoutview = new LayoutView(this, this.panelWin);
     }
 
     if (this.target.form.animationsActor) {
       this.sidebar.addFrameTab(
         "animationinspector",
         INSPECTOR_L10N.getStr("inspector.sidebar.animationInspectorTitle"),
--- a/devtools/client/inspector/layout/components/App.js
+++ b/devtools/client/inspector/layout/components/App.js
@@ -5,36 +5,39 @@
 "use strict";
 
 const { addons, createClass, createFactory, DOM: dom, 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("./Accordion"));
-const Grid = createFactory(require("./Grid"));
+const BoxModel = createFactory(require("devtools/client/inspector/boxmodel/components/BoxModel"));
+const Grid = createFactory(require("devtools/client/inspector/grids/components/Grid"));
 
-const BoxModel = createFactory(require("devtools/client/inspector/boxmodel/components/BoxModel"));
+const BoxModelTypes = require("devtools/client/inspector/boxmodel/types");
+const GridTypes = require("devtools/client/inspector/grids/types");
 
-const Types = require("../types");
-const { getStr } = require("../utils/l10n");
+const Accordion = createFactory(require("./Accordion"));
 
 const BOXMODEL_STRINGS_URI = "devtools/client/locales/boxmodel.properties";
 const BOXMODEL_L10N = new LocalizationHelper(BOXMODEL_STRINGS_URI);
 
+const LAYOUT_STRINGS_URI = "devtools/client/locales/layout.properties";
+const LAYOUT_L10N = new LocalizationHelper(LAYOUT_STRINGS_URI);
+
 const App = createClass({
 
   displayName: "App",
 
   propTypes: {
-    boxModel: PropTypes.shape(Types.boxModel).isRequired,
+    boxModel: PropTypes.shape(BoxModelTypes.boxModel).isRequired,
     getSwatchColorPickerTooltip: PropTypes.func.isRequired,
-    grids: PropTypes.arrayOf(PropTypes.shape(Types.grid)).isRequired,
-    highlighterSettings: PropTypes.shape(Types.highlighterSettings).isRequired,
+    grids: PropTypes.arrayOf(PropTypes.shape(GridTypes.grid)).isRequired,
+    highlighterSettings: PropTypes.shape(GridTypes.highlighterSettings).isRequired,
     setSelectedNode: PropTypes.func.isRequired,
     showBoxModelProperties: PropTypes.bool.isRequired,
     showGridOutline: PropTypes.bool.isRequired,
     onHideBoxModelHighlighter: PropTypes.func.isRequired,
     onSetGridOverlayColor: PropTypes.func.isRequired,
     onShowBoxModelEditor: PropTypes.func.isRequired,
     onShowBoxModelHighlighter: PropTypes.func.isRequired,
     onToggleGridHighlighter: PropTypes.func.isRequired,
@@ -53,17 +56,17 @@ const App = createClass({
         items: [
           {
             header: BOXMODEL_L10N.getStr("boxmodel.title"),
             component: BoxModel,
             componentProps: this.props,
             opened: true,
           },
           {
-            header: getStr("layout.header"),
+            header: LAYOUT_L10N.getStr("layout.header"),
             component: Grid,
             componentProps: this.props,
             opened: true,
           },
         ]
       })
     );
   },
--- a/devtools/client/inspector/layout/components/moz.build
+++ b/devtools/client/inspector/layout/components/moz.build
@@ -3,14 +3,9 @@
 # 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(
     'Accordion.css',
     'Accordion.js',
     'App.js',
-    'Grid.js',
-    'GridDisplaySettings.js',
-    'GridItem.js',
-    'GridList.js',
-    'GridOutline.js',
 )
--- a/devtools/client/inspector/layout/layout.js
+++ b/devtools/client/inspector/layout/layout.js
@@ -1,254 +1,83 @@
 /* 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 Services = require("Services");
-const { Task } = require("devtools/shared/task");
 
 const { createFactory, createElement } = require("devtools/client/shared/vendor/react");
 const { Provider } = require("devtools/client/shared/vendor/react-redux");
 
-const SwatchColorPickerTooltip = require("devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip");
-
-const {
-  updateGridColor,
-  updateGridHighlighted,
-  updateGrids,
-} = require("./actions/grids");
-const {
-  updateShowGridLineNumbers,
-  updateShowInfiniteLines,
-} = require("./actions/highlighter-settings");
-
 const App = createFactory(require("./components/App"));
 
 const { LocalizationHelper } = require("devtools/shared/l10n");
 const INSPECTOR_L10N =
   new LocalizationHelper("devtools/client/locales/inspector.properties");
 
-const SHOW_GRID_LINE_NUMBERS = "devtools.gridinspector.showGridLineNumbers";
 const SHOW_GRID_OUTLINE_PREF = "devtools.gridinspector.showGridOutline";
-const SHOW_INFINITE_LINES_PREF = "devtools.gridinspector.showInfiniteLines";
-
-// Default grid colors.
-const GRID_COLORS = [
-  "#05E4EE",
-  "#BB9DFF",
-  "#FFB53B",
-  "#71F362",
-  "#FF90FF",
-  "#FF90FF",
-  "#1B80FF",
-  "#FF2647"
-];
 
 function LayoutView(inspector, window) {
   this.document = window.document;
-  this.highlighters = inspector.highlighters;
   this.inspector = inspector;
   this.store = inspector.store;
-  this.walker = this.inspector.walker;
-
-  this.onGridLayoutChange = this.onGridLayoutChange.bind(this);
-  this.onHighlighterChange = this.onHighlighterChange.bind(this);
-  this.onSidebarSelect = this.onSidebarSelect.bind(this);
 
   this.init();
 }
 
 LayoutView.prototype = {
 
-  /**
-   * Initializes the layout view by fetching the LayoutFront from the walker, creating
-   * the redux store and adding the view into the inspector sidebar.
-   */
-  init: Task.async(function* () {
+  init() {
     if (!this.inspector) {
       return;
     }
 
     let {
       onHideBoxModelHighlighter,
       onShowBoxModelEditor,
       onShowBoxModelHighlighter,
     } = this.inspector.boxmodel.getComponentProps();
 
-    this.layoutInspector = yield this.inspector.walker.getLayoutInspector();
-
-    this.loadHighlighterSettings();
-
-    this.highlighters.on("grid-highlighter-hidden", this.onHighlighterChange);
-    this.highlighters.on("grid-highlighter-shown", this.onHighlighterChange);
-    this.inspector.sidebar.on("select", this.onSidebarSelect);
-
-    // Create a shared SwatchColorPicker instance to be reused by all GridItem components.
-    this.swatchColorPickerTooltip = new SwatchColorPickerTooltip(
-      this.inspector.toolbox.doc,
-      this.inspector,
-      {
-        supportsCssColor4ColorFunction: () => false
-      }
-    );
+    let {
+      getSwatchColorPickerTooltip,
+      setSelectedNode,
+      onSetGridOverlayColor,
+      onShowBoxModelHighlighterForNode,
+      onShowGridAreaHighlight,
+      onToggleGridHighlighter,
+      onToggleShowGridLineNumbers,
+      onToggleShowInfiniteLines,
+    } = this.inspector.gridInspector.getComponentProps();
 
     let app = App({
-      /**
-       * Retrieve the shared SwatchColorPicker instance.
-       */
-      getSwatchColorPickerTooltip: () => {
-        return this.swatchColorPickerTooltip;
-      },
-
-      /**
-       * Set the inspector selection.
-       *
-       * @param {NodeFront} nodeFront
-       *        The NodeFront corresponding to the new selection.
-       */
-      setSelectedNode: (nodeFront) => {
-        this.inspector.selection.setNodeFront(nodeFront, "layout-panel");
-      },
-
+      getSwatchColorPickerTooltip,
+      setSelectedNode,
       /**
        * Shows the box model properties under the box model if true, otherwise, hidden by
        * default.
        */
       showBoxModelProperties: true,
 
       /**
        * Shows the grid outline if user preferences are set to true, otherwise, hidden by
        * default.
        */
       showGridOutline: Services.prefs.getBoolPref(SHOW_GRID_OUTLINE_PREF),
 
       onHideBoxModelHighlighter,
-
-      /**
-       * Handler for a change in the grid overlay color picker for a grid container.
-       *
-       * @param  {NodeFront} node
-       *         The NodeFront of the grid container element for which the grid color is
-       *         being updated.
-       * @param  {String} color
-       *         A hex string representing the color to use.
-       */
-      onSetGridOverlayColor: (node, color) => {
-        this.store.dispatch(updateGridColor(node, color));
-        let { grids } = this.store.getState();
-
-        // If the grid for which the color was updated currently has a highlighter, update
-        // the color.
-        for (let grid of grids) {
-          if (grid.nodeFront === node && grid.highlighted) {
-            let highlighterSettings = this.getGridHighlighterSettings(node);
-            this.highlighters.showGridHighlighter(node, highlighterSettings);
-          }
-        }
-      },
-
+      onSetGridOverlayColor,
       onShowBoxModelEditor,
       onShowBoxModelHighlighter,
-
-     /**
-      * Shows the box-model highlighter on the element corresponding to the provided
-      * NodeFront.
-      *
-      * @param  {NodeFront} nodeFront
-      *         The node to highlight.
-      * @param  {Object} options
-      *         Options passed to the highlighter actor.
-      */
-      onShowBoxModelHighlighterForNode: (nodeFront, options) => {
-        let toolbox = this.inspector.toolbox;
-        toolbox.highlighterUtils.highlightNodeFront(nodeFront, options);
-      },
-
-      /**
-       * Highlights the grid area in the CSS Grid Highlighter for the given grid.
-       *
-       * @param  {NodeFront} node
-       *         The NodeFront of the grid container element for which the grid
-       *         highlighter is highlighted for.
-       * @param  {String} gridAreaName
-       *         The name of the grid area for which the grid highlighter
-       *         is highlighted for.
-       * @param  {String} color
-       *         The color of the grid area for which the grid highlighter
-       *         is highlighted for.
-       */
-      onShowGridAreaHighlight: (node, gridAreaName, color) => {
-        let { highlighterSettings } = this.store.getState();
-
-        highlighterSettings.showGridArea = gridAreaName;
-        highlighterSettings.color = color;
-
-        this.highlighters.showGridHighlighter(node, highlighterSettings);
-      },
-
-      /**
-       * Handler for a change in the input checkboxes in the GridList component.
-       * Toggles on/off the grid highlighter for the provided grid container element.
-       *
-       * @param  {NodeFront} node
-       *         The NodeFront of the grid container element for which the grid
-       *         highlighter is toggled on/off for.
-       */
-      onToggleGridHighlighter: node => {
-        let highlighterSettings = this.getGridHighlighterSettings(node);
-        this.highlighters.toggleGridHighlighter(node, highlighterSettings);
-      },
-
-      /**
-       * Handler for a change in the show grid line numbers checkbox in the
-       * GridDisplaySettings component. Toggles on/off the option to show the grid line
-       * numbers in the grid highlighter. Refreshes the shown grid highlighter for the
-       * grids currently highlighted.
-       *
-       * @param  {Boolean} enabled
-       *         Whether or not the grid highlighter should show the grid line numbers.
-       */
-      onToggleShowGridLineNumbers: enabled => {
-        this.store.dispatch(updateShowGridLineNumbers(enabled));
-        Services.prefs.setBoolPref(SHOW_GRID_LINE_NUMBERS, enabled);
-
-        let { grids } = this.store.getState();
-
-        for (let grid of grids) {
-          if (grid.highlighted) {
-            let highlighterSettings = this.getGridHighlighterSettings(grid.nodeFront);
-            this.highlighters.showGridHighlighter(grid.nodeFront, highlighterSettings);
-          }
-        }
-      },
-
-      /**
-       * Handler for a change in the extend grid lines infinitely checkbox in the
-       * GridDisplaySettings component. Toggles on/off the option to extend the grid
-       * lines infinitely in the grid highlighter. Refreshes the shown grid highlighter
-       * for grids currently highlighted.
-       *
-       * @param  {Boolean} enabled
-       *         Whether or not the grid highlighter should extend grid lines infinitely.
-       */
-      onToggleShowInfiniteLines: enabled => {
-        this.store.dispatch(updateShowInfiniteLines(enabled));
-        Services.prefs.setBoolPref(SHOW_INFINITE_LINES_PREF, enabled);
-
-        let { grids } = this.store.getState();
-
-        for (let grid of grids) {
-          if (grid.highlighted) {
-            let highlighterSettings = this.getGridHighlighterSettings(grid.nodeFront);
-            this.highlighters.showGridHighlighter(grid.nodeFront, highlighterSettings);
-          }
-        }
-      }
+      onShowBoxModelHighlighterForNode,
+      onShowGridAreaHighlight,
+      onToggleGridHighlighter,
+      onToggleShowGridLineNumbers,
+      onToggleShowInfiniteLines,
     });
 
     let provider = createElement(Provider, {
       store: this.store,
       id: "layoutview",
       title: INSPECTOR_L10N.getStr("inspector.sidebar.layoutViewTitle2"),
       key: "layoutview",
     }, app);
@@ -256,170 +85,22 @@ LayoutView.prototype = {
     let defaultTab = Services.prefs.getCharPref("devtools.inspector.activeSidebar");
 
     this.inspector.addSidebarTab(
       "layoutview",
       INSPECTOR_L10N.getStr("inspector.sidebar.layoutViewTitle2"),
       provider,
       defaultTab == "layoutview"
     );
-  }),
-
-  /**
-   * Destruction function called when the inspector is destroyed. Removes event listeners
-   * and cleans up references.
-   */
-  destroy() {
-    this.highlighters.off("grid-highlighter-hidden", this.onHighlighterChange);
-    this.highlighters.off("grid-highlighter-shown", this.onHighlighterChange);
-    this.inspector.sidebar.off("select", this.onSidebarSelect);
-    this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
-
-    this.document = null;
-    this.inspector = null;
-    this.layoutInspector = null;
-    this.store = null;
-    this.walker = null;
-  },
-
-  /**
-   * Returns the color set for the grid highlighter associated with the provided
-   * nodeFront.
-   *
-   * @param  {NodeFront} nodeFront
-   *         The NodeFront for which we need the color.
-   */
-  getGridColorForNodeFront(nodeFront) {
-    let { grids } = this.store.getState();
-
-    for (let grid of grids) {
-      if (grid.nodeFront === nodeFront) {
-        return grid.color;
-      }
-    }
-
-    return null;
-  },
-
-  /**
-   * Create a highlighter settings object for the provided nodeFront.
-   *
-   * @param  {NodeFront} nodeFront
-   *         The NodeFront for which we need highlighter settings.
-   */
-  getGridHighlighterSettings(nodeFront) {
-    let { highlighterSettings } = this.store.getState();
-
-    // Get the grid color for the provided nodeFront.
-    let color = this.getGridColorForNodeFront(nodeFront);
-
-    // Merge the grid color to the generic highlighter settings.
-    return Object.assign({}, highlighterSettings, {
-      color
-    });
-  },
-
-  /**
-   * Returns true if the layout panel is visible, and false otherwise.
-   */
-  isPanelVisible() {
-    return this.inspector.toolbox.currentToolId === "inspector" &&
-           this.inspector.sidebar &&
-           this.inspector.sidebar.getCurrentTabID() === "layoutview";
-  },
-
-  /**
-   * Load the grid highligher display settings into the store from the stored preferences.
-   */
-  loadHighlighterSettings() {
-    let { dispatch } = this.store;
-
-    let showGridLineNumbers = Services.prefs.getBoolPref(SHOW_GRID_LINE_NUMBERS);
-    let showInfinteLines = Services.prefs.getBoolPref(SHOW_INFINITE_LINES_PREF);
-
-    dispatch(updateShowGridLineNumbers(showGridLineNumbers));
-    dispatch(updateShowInfiniteLines(showInfinteLines));
   },
 
   /**
-   * Updates the grid panel by dispatching the new grid data. This is called when the
-   * layout view becomes visible or the view needs to be updated with new grid data.
-   *
-   * @param {Array|null} gridFronts
-   *        Optional array of all GridFront in the current page.
+   * Destruction function called when the inspector is destroyed. Cleans up references.
    */
-  updateGridPanel: Task.async(function* (gridFronts) {
-    // Stop refreshing if the inspector or store is already destroyed.
-    if (!this.inspector || !this.store) {
-      return;
-    }
-
-    // Get all the GridFront from the server if no gridFronts were provided.
-    if (!gridFronts) {
-      gridFronts = yield this.layoutInspector.getAllGrids(this.walker.rootNode);
-    }
-
-    let grids = [];
-    for (let i = 0; i < gridFronts.length; i++) {
-      let grid = gridFronts[i];
-      let nodeFront = yield this.walker.getNodeFromActor(grid.actorID, ["containerEl"]);
-
-      let fallbackColor = GRID_COLORS[i % GRID_COLORS.length];
-      let color = this.getGridColorForNodeFront(nodeFront) || fallbackColor;
-
-      grids.push({
-        id: i,
-        color,
-        gridFragments: grid.gridFragments,
-        highlighted: nodeFront == this.highlighters.gridHighlighterShown,
-        nodeFront,
-      });
-    }
-
-    this.store.dispatch(updateGrids(grids));
-  }),
-
-  /**
-   * Handler for "grid-layout-changed" events emitted from the LayoutActor.
-   *
-   * @param  {Array} grids
-   *         Array of all GridFront in the current page.
-   */
-  onGridLayoutChange(grids) {
-    if (this.isPanelVisible()) {
-      this.updateGridPanel(grids);
-    }
-  },
-
-  /**
-   * Handler for "grid-highlighter-shown" and "grid-highlighter-hidden" events emitted
-   * from the HighlightersOverlay. Updates the NodeFront's grid highlighted state.
-   *
-   * @param  {Event} event
-   *         Event that was triggered.
-   * @param  {NodeFront} nodeFront
-   *         The NodeFront of the grid container element for which the grid highlighter
-   *         is shown for.
-   */
-  onHighlighterChange(event, nodeFront) {
-    let highlighted = event === "grid-highlighter-shown";
-    this.store.dispatch(updateGridHighlighted(nodeFront, highlighted));
-  },
-
-  /**
-   * Handler for the inspector sidebar select event. Starts listening for
-   * "grid-layout-changed" if the layout panel is visible. Otherwise, stop
-   * listening for grid layout changes. Finally, refresh the layout view if
-   * it is visible.
-   */
-  onSidebarSelect() {
-    if (!this.isPanelVisible()) {
-      this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
-      return;
-    }
-
-    this.layoutInspector.on("grid-layout-changed", this.onGridLayoutChange);
-    this.updateGridPanel();
+  destroy() {
+    this.document = null;
+    this.inspector = null;
+    this.store = null;
   },
 
 };
 
 module.exports = LayoutView;
--- a/devtools/client/inspector/layout/moz.build
+++ b/devtools/client/inspector/layout/moz.build
@@ -1,17 +1,13 @@
 # -*- 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/.
 
 DIRS += [
-    'actions',
     'components',
-    'reducers',
-    'utils',
 ]
 
 DevToolsModules(
     'layout.js',
-    'types.js',
 )
--- a/devtools/client/inspector/moz.build
+++ b/devtools/client/inspector/moz.build
@@ -2,16 +2,17 @@
 # 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/.
 
 DIRS += [
     'boxmodel',
     'components',
     'computed',
     'fonts',
+    'grids',
     'layout',
     'markup',
     'rules',
     'shared'
 ]
 
 DevToolsModules(
     'breadcrumbs.js',
--- a/devtools/client/inspector/reducers.js
+++ b/devtools/client/inspector/reducers.js
@@ -3,10 +3,10 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 // This file exposes the Redux reducers of the box model, grid and grid highlighter
 // settings.
 
 exports.boxModel = require("devtools/client/inspector/boxmodel/reducers/box-model");
-exports.grids = require("devtools/client/inspector/layout/reducers/grids");
-exports.highlighterSettings = require("devtools/client/inspector/layout/reducers/highlighter-settings");
+exports.grids = require("devtools/client/inspector/grids/reducers/grids");
+exports.highlighterSettings = require("devtools/client/inspector/grids/reducers/highlighter-settings");
--- a/devtools/client/shared/browser-loader.js
+++ b/devtools/client/shared/browser-loader.js
@@ -9,16 +9,17 @@ const { devtools } = Cu.import("resource
 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/grids",
   "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",