Bug 1317102 - Part 6: Hide the grid outline when multiple grids are highlighted. r=pbro
authorGabriel Luong <gabriel.luong@gmail.com>
Mon, 08 Oct 2018 13:40:47 -0400
changeset 488391 e30423fbf14ce12ad9ca3c18a5a062bb9398088b
parent 488390 0dcf343133e9c8339c2d1d989f3d2c7f2a243f53
child 488392 b6873a75a4693ee420c7842957894c96b3336ee2
push id246
push userfmarier@mozilla.com
push dateSat, 13 Oct 2018 00:15:40 +0000
reviewerspbro
bugs1317102
milestone64.0a1
Bug 1317102 - Part 6: Hide the grid outline when multiple grids are highlighted. r=pbro
devtools/client/inspector/grids/components/Grid.js
devtools/client/inspector/grids/components/GridOutline.js
devtools/client/inspector/grids/test/browser.ini
devtools/client/inspector/grids/test/browser_grids_grid-outline-multiple-grids.js
devtools/client/inspector/grids/test/browser_grids_grid-outline-writing-mode.js
--- a/devtools/client/inspector/grids/components/Grid.js
+++ b/devtools/client/inspector/grids/components/Grid.js
@@ -38,38 +38,39 @@ class Grid extends PureComponent {
       onToggleShowGridAreas: PropTypes.func.isRequired,
       onToggleShowGridLineNumbers: PropTypes.func.isRequired,
       onToggleShowInfiniteLines: PropTypes.func.isRequired,
       setSelectedNode: PropTypes.func.isRequired,
     };
   }
 
   render() {
+    if (!this.props.grids.length) {
+      return (
+        dom.div({ className: "devtools-sidepanel-no-result" },
+          getStr("layout.noGridsOnThisPage")
+        )
+      );
+    }
+
     const {
       getSwatchColorPickerTooltip,
       grids,
       highlighterSettings,
       onHideBoxModelHighlighter,
       onSetGridOverlayColor,
       onShowBoxModelHighlighterForNode,
       onShowGridOutlineHighlight,
       onToggleShowGridAreas,
       onToggleGridHighlighter,
       onToggleShowGridLineNumbers,
       onToggleShowInfiniteLines,
       setSelectedNode,
     } = this.props;
-
-    if (!grids.length) {
-      return (
-        dom.div({ className: "devtools-sidepanel-no-result" },
-          getStr("layout.noGridsOnThisPage")
-        )
-      );
-    }
+    const highlightedGrids = grids.filter(grid => grid.highlighted);
 
     return (
       dom.div({ id: "layout-grid-container" },
         dom.div({ className: "grid-content" },
           GridList({
             getSwatchColorPickerTooltip,
             grids,
             onHideBoxModelHighlighter,
@@ -80,18 +81,21 @@ class Grid extends PureComponent {
           }),
           GridDisplaySettings({
             highlighterSettings,
             onToggleShowGridAreas,
             onToggleShowGridLineNumbers,
             onToggleShowInfiniteLines,
           })
         ),
-        GridOutline({
-          grids,
-          onShowGridOutlineHighlight,
-        })
+        highlightedGrids.length === 1 ?
+          GridOutline({
+            grids,
+            onShowGridOutlineHighlight,
+          })
+          :
+          null
       )
     );
   }
 }
 
 module.exports = Grid;
--- a/devtools/client/inspector/grids/components/GridOutline.js
+++ b/devtools/client/inspector/grids/components/GridOutline.js
@@ -39,62 +39,61 @@ const VIEWPORT_MAX_HEIGHT = 150;
 class GridOutline extends PureComponent {
   static get propTypes() {
     return {
       grids: PropTypes.arrayOf(PropTypes.shape(Types.grid)).isRequired,
       onShowGridOutlineHighlight: PropTypes.func.isRequired,
     };
   }
 
+  static getDerivedStateFromProps(props) {
+    const selectedGrid = props.grids.find(grid => grid.highlighted);
+
+    // Store the height of the grid container in the component state to prevent overflow
+    // issues. We want to store the width of the grid container as well so that the
+    // viewbox is only the calculated width of the grid outline.
+    const { width, height } = selectedGrid && selectedGrid.gridFragments.length
+                            ? getTotalWidthAndHeight(selectedGrid)
+                            : { width: 0, height: 0 };
+    let showOutline;
+
+    if (selectedGrid && selectedGrid.gridFragments.length) {
+      const { cols, rows } = selectedGrid.gridFragments[0];
+
+      // Show the grid outline if both the rows/columns are less than or equal
+      // to their max prefs.
+      showOutline = (cols.lines.length <= GRID_OUTLINE_MAX_COLUMNS_PREF) &&
+                    (rows.lines.length <= GRID_OUTLINE_MAX_ROWS_PREF);
+    }
+
+    return { height, width, selectedGrid, showOutline };
+  }
+
   constructor(props) {
     super(props);
 
     this.state = {
       height: 0,
       selectedGrid: null,
       showOutline: true,
       width: 0,
     };
 
     this.doHighlightCell = this.doHighlightCell.bind(this);
     this.getGridAreaName = this.getGridAreaName.bind(this);
     this.getHeight = this.getHeight.bind(this);
-    this.getTotalWidthAndHeight = this.getTotalWidthAndHeight.bind(this);
     this.onHighlightCell = this.onHighlightCell.bind(this);
     this.renderCannotShowOutlineText = this.renderCannotShowOutlineText.bind(this);
     this.renderGrid = this.renderGrid.bind(this);
     this.renderGridCell = this.renderGridCell.bind(this);
     this.renderGridOutline = this.renderGridOutline.bind(this);
     this.renderGridOutlineBorder = this.renderGridOutlineBorder.bind(this);
     this.renderOutline = this.renderOutline.bind(this);
   }
 
-  componentWillReceiveProps({ grids }) {
-    const selectedGrid = grids.find(grid => grid.highlighted);
-
-    // Store the height of the grid container in the component state to prevent overflow
-    // issues. We want to store the width of the grid container as well so that the
-    // viewbox is only the calculated width of the grid outline.
-    const { width, height } = selectedGrid && selectedGrid.gridFragments.length
-                            ? this.getTotalWidthAndHeight(selectedGrid)
-                            : { width: 0, height: 0 };
-    let showOutline;
-
-    if (selectedGrid && selectedGrid.gridFragments.length) {
-      const { cols, rows } = selectedGrid.gridFragments[0];
-
-      // Show the grid outline if both the rows/columns are less than or equal
-      // to their max prefs.
-      showOutline = (cols.lines.length <= GRID_OUTLINE_MAX_COLUMNS_PREF) &&
-                    (rows.lines.length <= GRID_OUTLINE_MAX_ROWS_PREF);
-    }
-
-    this.setState({ height, width, selectedGrid, showOutline });
-  }
-
   doHighlightCell(target, hide) {
     const {
       grids,
       onShowGridOutlineHighlight,
     } = this.props;
     const name = target.dataset.gridAreaName;
     const id = target.dataset.gridId;
     const gridFragmentIndex = target.dataset.gridFragmentIndex;
@@ -155,48 +154,16 @@ class GridOutline extends PureComponent 
     } else if (height <= VIEWPORT_MIN_HEIGHT) {
       return VIEWPORT_MIN_HEIGHT;
     }
 
     return height;
   }
 
   /**
-   * Get the width and height of a given grid.
-   *
-   * @param  {Object} grid
-   *         A single grid container in the document.
-   * @return {Object} An object like { width, height }
-   */
-  getTotalWidthAndHeight(grid) {
-    // TODO: We are drawing the first fragment since only one is currently being stored.
-    // In the future we will need to iterate over all fragments of a grid.
-    const { gridFragments } = grid;
-    const { rows, cols } = gridFragments[0];
-
-    let height = 0;
-    for (let i = 0; i < rows.lines.length - 1; i++) {
-      height += GRID_CELL_SCALE_FACTOR * (rows.tracks[i].breadth / 100);
-    }
-
-    let width = 0;
-    for (let i = 0; i < cols.lines.length - 1; i++) {
-      width += GRID_CELL_SCALE_FACTOR * (cols.tracks[i].breadth / 100);
-    }
-
-    // All writing modes other than horizontal-tb (the initial value) involve a 90 deg
-    // rotation, so swap width and height.
-    if (grid.writingMode != "horizontal-tb") {
-      [ width, height ] = [ height, width ];
-    }
-
-    return { width, height };
-  }
-
-  /**
    * Displays a message text "Cannot show outline for this grid".
    */
   renderCannotShowOutlineText() {
     return (
       dom.div({ className: "grid-outline-text" },
         dom.span(
           {
             className: "grid-outline-text-icon",
@@ -391,9 +358,41 @@ class GridOutline extends PureComponent 
         },
         this.renderOutline()
       )
       :
       null;
   }
 }
 
+/**
+ * Get the width and height of a given grid.
+ *
+ * @param  {Object} grid
+ *         A single grid container in the document.
+ * @return {Object} An object like { width, height }
+ */
+function getTotalWidthAndHeight(grid) {
+  // TODO: We are drawing the first fragment since only one is currently being stored.
+  // In the future we will need to iterate over all fragments of a grid.
+  const { gridFragments } = grid;
+  const { rows, cols } = gridFragments[0];
+
+  let height = 0;
+  for (let i = 0; i < rows.lines.length - 1; i++) {
+    height += GRID_CELL_SCALE_FACTOR * (rows.tracks[i].breadth / 100);
+  }
+
+  let width = 0;
+  for (let i = 0; i < cols.lines.length - 1; i++) {
+    width += GRID_CELL_SCALE_FACTOR * (cols.tracks[i].breadth / 100);
+  }
+
+  // All writing modes other than horizontal-tb (the initial value) involve a 90 deg
+  // rotation, so swap width and height.
+  if (grid.writingMode != "horizontal-tb") {
+    [ width, height ] = [ height, width ];
+  }
+
+  return { width, height };
+}
+
 module.exports = GridOutline;
--- a/devtools/client/inspector/grids/test/browser.ini
+++ b/devtools/client/inspector/grids/test/browser.ini
@@ -28,16 +28,17 @@ skip-if = (verify && (os == 'win' || os 
 [browser_grids_grid-list-toggle-grids_01.js]
 [browser_grids_grid-list-toggle-grids_02.js]
 [browser_grids_grid-list-toggle-multiple-grids.js]
 [browser_grids_grid-outline-cannot-show-outline.js]
 [browser_grids_grid-outline-highlight-area.js]
 skip-if = (verify && (os == 'win'))
 [browser_grids_grid-outline-highlight-cell.js]
 skip-if = (verify && (os == 'win'))
+[browser_grids_grid-outline-multiple-grids.js]
 [browser_grids_grid-outline-selected-grid.js]
 [browser_grids_grid-outline-updates-on-grid-change.js]
 [browser_grids_grid-outline-writing-mode.js]
 skip-if = (verify && (os == 'win'))
 [browser_grids_highlighter-setting-rules-grid-toggle.js]
 [browser_grids_number-of-css-grids-telemetry.js]
 [browser_grids_persist-color-palette.js]
 [browser_grids_restored-after-reload.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/grids/test/browser_grids_grid-outline-multiple-grids.js
@@ -0,0 +1,64 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests that the grid outline is not shown when more than one grid is highlighted.
+
+const TEST_URI = `
+  <style type='text/css'>
+    .grid {
+      display: grid;
+    }
+  </style>
+  <div id="grid1" class="grid">
+    <div class="cell1">cell1</div>
+    <div class="cell2">cell2</div>
+  </div>
+  <div id="grid2" class="grid">
+    <div class="cell1">cell1</div>
+    <div class="cell2">cell2</div>
+  </div>
+`;
+
+add_task(async function() {
+  await pushPref("devtools.gridinspector.maxHighlighters", 2);
+  await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+  const { inspector, gridInspector } = await openLayoutView();
+  const { document: doc } = gridInspector;
+  const { highlighters, store } = inspector;
+
+  await selectNode("#grid1", inspector);
+  const gridList = doc.getElementById("grid-list");
+  const checkbox1 = gridList.children[0].querySelector("input");
+  const checkbox2 = gridList.children[1].querySelector("input");
+
+  info("Toggling ON the CSS grid highlighter for #grid1.");
+  let onHighlighterShown = highlighters.once("grid-highlighter-shown");
+  const onGridOutlineRendered = waitForDOM(doc, "#grid-cell-group rect", 2);
+  let onCheckboxChange = waitUntilState(store, state =>
+    state.grids.length === 2 &&
+    state.grids[0].highlighted &&
+    !state.grids[1].highlighted);
+  checkbox1.click();
+  await onHighlighterShown;
+  await onCheckboxChange;
+  const elements = await onGridOutlineRendered;
+
+  info("Checking the grid outline for #grid1 is shown.");
+  ok(doc.getElementById("grid-outline-container"), "Grid outline container is rendered.");
+  is(elements.length, 2, "Grid outline is shown.");
+
+  info("Toggling ON the CSS grid highlighter for #grid2.");
+  onHighlighterShown = highlighters.once("grid-highlighter-shown");
+  onCheckboxChange = waitUntilState(store, state =>
+    state.grids.length === 2 &&
+    state.grids[0].highlighted &&
+    state.grids[1].highlighted);
+  checkbox2.click();
+  await onHighlighterShown;
+  await onCheckboxChange;
+
+  info("Checking the grid outline is not shown.");
+  ok(!doc.getElementById("grid-outline-container"), "Grid outline is not rendered.");
+});
--- a/devtools/client/inspector/grids/test/browser_grids_grid-outline-writing-mode.js
+++ b/devtools/client/inspector/grids/test/browser_grids_grid-outline-writing-mode.js
@@ -56,16 +56,17 @@ const TEST_URI = `
   <div class="grid s-lr">
     <div id="cella">Cell A</div>
     <div id="cellb">Cell B</div>
     <div id="cellc">Cell C</div>
   </div>
 `;
 
 add_task(async function() {
+  await pushPref("devtools.gridinspector.maxHighlighters", 1);
   await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
 
   const { inspector, gridInspector } = await openLayoutView();
   const { document: doc } = gridInspector;
   const { highlighters, store } = inspector;
 
   info("Checking the initial state of the Grid Inspector.");
   ok(!doc.getElementById("grid-outline-container"),