Bug 1348471 - Display a message when the grid outline cannot effectively be fitted inside the layout panel. r=gl
authorMicah Tigley <tigleym@gmail.com>
Wed, 24 May 2017 19:40:07 -0600
changeset 409384 327ecc8de0295e4a7d64994dfd7add0128c50e2e
parent 409383 47e0df5e8bd1318caa8ae9984d117a7492493f5a
child 409385 c3a2ed2ce9541b1d6684f6b6792fb78f7361f8ab
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgl
bugs1348471
milestone55.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 1348471 - Display a message when the grid outline cannot effectively be fitted inside the layout panel. r=gl MozReview-Commit-ID: 57cikdLW3IV
devtools/client/inspector/grids/components/GridOutline.js
devtools/client/jar.mn
devtools/client/locales/en-US/layout.properties
devtools/client/themes/images/sad-face.svg
devtools/client/themes/layout.css
--- a/devtools/client/inspector/grids/components/GridOutline.js
+++ b/devtools/client/inspector/grids/components/GridOutline.js
@@ -3,23 +3,28 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const { addons, createClass, DOM: dom, PropTypes } =
   require("devtools/client/shared/vendor/react");
 
 const Types = require("../types");
+const { getStr } = require("../utils/l10n");
 
 const COLUMNS = "cols";
 const ROWS = "rows";
 
 // The delay prior to executing the grid cell highlighting.
 const GRID_HIGHLIGHTING_DEBOUNCE = 50;
 
+// Minimum height/width a grid cell can be
+const MIN_CELL_HEIGHT = 5;
+const MIN_CELL_WIDTH = 5;
+
 // Move SVG grid to the right 100 units, so that it is not flushed against the edge of
 // layout border
 const TRANSLATE_X = 0;
 const TRANSLATE_Y = 0;
 
 const GRID_CELL_SCALE_FACTOR = 50;
 
 const VIEWPORT_MIN_HEIGHT = 100;
@@ -35,33 +40,34 @@ module.exports = createClass({
     onShowGridCellHighlight: PropTypes.func.isRequired,
     onShowGridLineNamesHighlight: PropTypes.func.isRequired,
   },
 
   mixins: [ addons.PureRenderMixin ],
 
   getInitialState() {
     return {
+      height: 0,
       selectedGrid: null,
-      height: 0,
+      showOutline: true,
       width: 0,
     };
   },
 
   componentWillReceiveProps({ grids }) {
     let 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.
     let { width, height } = selectedGrid
                             ? this.getTotalWidthAndHeight(selectedGrid)
                             : { width: 0, height: 0 };
 
-    this.setState({ height, width, selectedGrid });
+    this.setState({ height, width, selectedGrid, showOutline: true });
   },
 
   /**
    * 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 }
@@ -130,16 +136,17 @@ module.exports = createClass({
   highlightCell(e) {
     // Debounce the highlighting of cells.
     // This way we don't end up sending many requests to the server for highlighting when
     // cells get hovered in a rapid succession We only send a request if the user settles
     // on a cell for some time.
     if (this.highlightTimeout) {
       clearTimeout(this.highlightTimeout);
     }
+
     this.highlightTimeout = setTimeout(() => {
       this.doHighlightCell(e);
       this.highlightTimeout = null;
     }, GRID_HIGHLIGHTING_DEBOUNCE);
   },
 
   doHighlightCell({ target }) {
     const {
@@ -160,16 +167,35 @@ module.exports = createClass({
 
     if (fragmentIndex && rowNumber && columnNumber) {
       onShowGridCellHighlight(grids[id].nodeFront, color, fragmentIndex,
         rowNumber, columnNumber);
     }
   },
 
   /**
+    * 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",
+          title: getStr("layout.cannotShowGridOutline.title")
+        }
+      ),
+      getStr("layout.cannotShowGridOutline")
+    );
+  },
+
+  /**
     * Renders the grid outline for the given grid container object.
     *
     * @param  {Object} grid
     *         A single grid container in the document.
     */
   renderGrid(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.
@@ -187,16 +213,24 @@ module.exports = createClass({
 
     // Draw the cells contained within the grid outline border.
     for (let rowNumber = 1; rowNumber <= numberOfRows; rowNumber++) {
       height = GRID_CELL_SCALE_FACTOR * (rows.tracks[rowNumber - 1].breadth / 100);
 
       for (let columnNumber = 1; columnNumber <= numberOfColumns; columnNumber++) {
         width = GRID_CELL_SCALE_FACTOR * (cols.tracks[columnNumber - 1].breadth / 100);
 
+        // If a grid cell is less than the minimum pixels in width or height,
+        // do not render the outline at all.
+        if (width < MIN_CELL_WIDTH || height < MIN_CELL_HEIGHT) {
+          this.setState({ showOutline: false });
+
+          return [];
+        }
+
         const gridAreaName = this.getGridAreaName(columnNumber, rowNumber, areas);
         const gridCell = this.renderGridCell(id, gridFragmentIndex, x, y,
                                              rowNumber, columnNumber, color, gridAreaName,
                                              width, height);
 
         rectangles.push(gridCell);
         x += width;
       }
@@ -415,27 +449,45 @@ module.exports = createClass({
     const lineNumber = target.dataset.gridLineNumber;
     const type = target.dataset.gridLineType;
     const color = target.closest(".grid-cell-group").dataset.gridLineColor;
 
     onShowGridLineNamesHighlight(grids[id].nodeFront, fragmentIndex, color,
       lineNumber, type);
   },
 
-  render() {
-    const { selectedGrid, height, width } = this.state;
+  renderOutline() {
+    const {
+      height,
+      selectedGrid,
+      showOutline,
+      width,
+    } = this.state;
 
-    return selectedGrid ?
+    return showOutline ?
       dom.svg(
         {
-          className: "grid-outline",
           width: "100%",
           height: this.getHeight(),
           viewBox: `${TRANSLATE_X} ${TRANSLATE_Y} ${width} ${height}`,
         },
         this.renderGridOutline(selectedGrid),
         this.renderGridLines(selectedGrid)
       )
       :
+      this.renderCannotShowOutlineText();
+  },
+
+  render() {
+    const { selectedGrid } = this.state;
+
+    return selectedGrid ?
+      dom.div(
+        {
+          className: "grid-outline",
+        },
+        this.renderOutline()
+      )
+      :
       null;
   },
 
 });
--- a/devtools/client/jar.mn
+++ b/devtools/client/jar.mn
@@ -211,16 +211,17 @@ devtools.jar:
     skin/images/profiler-stopwatch.svg (themes/images/profiler-stopwatch.svg)
     skin/images/debugging-addons.svg (themes/images/debugging-addons.svg)
     skin/images/debugging-tabs.svg (themes/images/debugging-tabs.svg)
     skin/images/debugging-workers.svg (themes/images/debugging-workers.svg)
     skin/images/gcli_sec_bad.svg (themes/images/gcli_sec_bad.svg)
     skin/images/gcli_sec_good.svg (themes/images/gcli_sec_good.svg)
     skin/images/gcli_sec_moderate.svg (themes/images/gcli_sec_moderate.svg)
     skin/images/globe.svg (themes/images/globe.svg)
+    skin/images/sad-face.svg (themes/images/sad-face.svg)
     skin/images/tool-options.svg (themes/images/tool-options.svg)
     skin/images/tool-webconsole.svg (themes/images/tool-webconsole.svg)
     skin/images/tool-canvas.svg (themes/images/tool-canvas.svg)
     skin/images/tool-debugger.svg (themes/images/tool-debugger.svg)
     skin/images/tool-debugger-paused.svg (themes/images/tool-debugger-paused.svg)
     skin/images/tool-inspector.svg (themes/images/tool-inspector.svg)
     skin/images/tool-shadereditor.svg (themes/images/tool-shadereditor.svg)
     skin/images/tool-styleeditor.svg (themes/images/tool-styleeditor.svg)
--- a/devtools/client/locales/en-US/layout.properties
+++ b/devtools/client/locales/en-US/layout.properties
@@ -2,16 +2,21 @@
 # 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/.
 
 # LOCALIZATION NOTE This file contains the Layout Inspector strings.
 # The Layout Inspector is a panel accessible in the Inspector sidebar.
 # The Layout Inspector may need to be enabled in about:config by setting
 # devtools.layoutview.enabled to true.
 
+# LOCALIZATION NOTE (layout.cannotShowGridOutline, layout.cannotSHowGridOutline.title):
+# In the case where the grid outline cannot be effectively displayed.
+layout.cannotShowGridOutline=Cannot show outline for this grid
+layout.cannotShowGridOutline.title=The selected grid’s outline cannot effectively fit inside the layout panel for it to be usable.
+
 # LOCALIZATION NOTE (layout.displayNumbersOnLines): Label of the display numbers on lines
 # setting option in the CSS Grid pane.
 layout.displayNumbersOnLines=Display numbers on lines
 
 # LOCALIZATION NOTE (layout.extendGridLinesInfinitely): Label of the extend grid lines
 # infinitely setting option in the CSS Grid pane.
 layout.extendGridLinesInfinitely=Extend grid lines infinitely
 
new file mode 100644
--- /dev/null
+++ b/devtools/client/themes/images/sad-face.svg
@@ -0,0 +1,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/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="#D92215">
+  <path d="M8 14.5c-3.6 0-6.5-2.9-6.5-6.5S4.4 1.5 8 1.5s6.5 2.9 6.5 6.5-2.9 6.5-6.5 6.5zm0-12C5 2.5 2.5 5 2.5 8S5 13.5 8 13.5 13.5 11 13.5 8 11 2.5 8 2.5z"/>
+  <circle cx="5" cy="6" r="1" transform="translate(1 1)"/>
+  <circle cx="9" cy="6" r="1" transform="translate(1 1)"/>
+  <path d="M5.5 11c-.1 0-.2 0-.3-.1-.2-.1-.3-.4-.1-.7C6 9 7 8.5 8.1 8.5c1.7.1 2.8 1.7 2.8 1.8.2.2.1.5-.1.7-.2.1-.6 0-.7-.2 0 0-.9-1.3-2-1.3-.7 0-1.4.4-2.1 1.3-.2.2-.4.2-.5.2z"/>
+</svg>
--- a/devtools/client/themes/layout.css
+++ b/devtools/client/themes/layout.css
@@ -54,45 +54,40 @@
 
 #layout-grid-container {
   display: flex;
   flex-direction: column;
   margin: 5px;
 }
 
 /**
- * Grid Outline
- */
-
-.grid-outline {
-  margin-top: 10px;
-  overflow: visible;
-}
-
-/**
  * Grid Content
  */
 
 .grid-content {
   display: flex;
   flex-wrap: wrap;
   flex: 1;
-  margin-top: 10px;
+  margin: 5px 0;
 }
 
 .grid-container:first-child {
   margin-bottom: 10px;
 }
 
 /**
  * Grid Outline
  */
 
-#grid-outline {
-  margin: 5px auto;
+.grid-outline {
+  margin: 5px 0;
+}
+
+.grid-outline svg {
+  overflow: visible;
 }
 
 .grid-outline-border {
   fill: none;
   stroke: currentColor;
   stroke-width: 0.75;
   vector-effect: non-scaling-stroke;
 }
@@ -109,16 +104,30 @@
   fill: currentColor;
 }
 
 .grid-outline-line {
   opacity: 0;
   stroke-width: 10;
 }
 
+.grid-outline-text {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: var(--theme-graphs-full-red);
+}
+
+.grid-outline-text-icon {
+  background: url("chrome://devtools/skin/images/sad-face.svg");
+  margin-inline-end: 5px;
+  width: 16px;
+  height: 16px;
+}
+
 /**
  * Container when no grids are present
  */
 
 .layout-no-grids {
   font-style: italic;
   text-align: center;
   padding: 0.5em;