Bug 1343777 - Display grid cell highlights on mouseover events for grid outline. r?gl draft
authorMicah Tigley <tigleym@gmail.com>
Thu, 02 Mar 2017 00:16:10 -0700
changeset 494270 14000eae54b2b36a0b6b9cda30ae2c368b721fc7
parent 491665 e91de6fb2b3dce9c932428265b0fdb630ea470d7
child 548070 7ebaa4b1af2cb0db5fdb7b4fa470164e73938aa2
push id48000
push userbmo:tigleym@gmail.com
push dateMon, 06 Mar 2017 23:35:06 +0000
reviewersgl
bugs1343777
milestone54.0a1
Bug 1343777 - Display grid cell highlights on mouseover events for grid outline. r?gl MozReview-Commit-ID: ErCPdqaaIvs
devtools/client/inspector/grids/components/Grid.js
devtools/client/inspector/grids/components/GridOutline.js
devtools/client/inspector/grids/grid-inspector.js
devtools/client/inspector/layout/layout.js
devtools/server/actors/highlighters/css-grid.js
--- a/devtools/client/inspector/grids/components/Grid.js
+++ b/devtools/client/inspector/grids/components/Grid.js
@@ -23,16 +23,17 @@ module.exports = createClass({
     grids: PropTypes.arrayOf(PropTypes.shape(Types.grid)).isRequired,
     highlighterSettings: PropTypes.shape(Types.highlighterSettings).isRequired,
     setSelectedNode: PropTypes.func.isRequired,
     showGridOutline: PropTypes.bool.isRequired,
     onHideBoxModelHighlighter: PropTypes.func.isRequired,
     onSetGridOverlayColor: PropTypes.func.isRequired,
     onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
     onShowGridAreaHighlight: PropTypes.func.isRequired,
+    onShowGridCellHighlight: PropTypes.func.isRequired,
     onToggleGridHighlighter: PropTypes.func.isRequired,
     onToggleShowGridLineNumbers: PropTypes.func.isRequired,
     onToggleShowInfiniteLines: PropTypes.func.isRequired,
   },
 
   mixins: [ addons.PureRenderMixin ],
 
   render() {
@@ -44,27 +45,29 @@ module.exports = createClass({
       showGridOutline,
       onHideBoxModelHighlighter,
       onSetGridOverlayColor,
       onShowBoxModelHighlighterForNode,
       onToggleGridHighlighter,
       onToggleShowGridLineNumbers,
       onToggleShowInfiniteLines,
       onShowGridAreaHighlight,
+      onShowGridCellHighlight,
     } = this.props;
 
     return grids.length ?
       dom.div(
         {
           id: "layout-grid-container",
         },
         showGridOutline ?
           GridOutline({
             grids,
             onShowGridAreaHighlight,
+            onShowGridCellHighlight,
           })
           :
           null,
         dom.div(
           {
             className: "grid-content",
           },
           GridList({
--- a/devtools/client/inspector/grids/components/GridOutline.js
+++ b/devtools/client/inspector/grids/components/GridOutline.js
@@ -19,16 +19,17 @@ const VIEWPORT_WIDTH = 450;
 
 module.exports = createClass({
 
   displayName: "GridOutline",
 
   propTypes: {
     grids: PropTypes.arrayOf(PropTypes.shape(Types.grid)).isRequired,
     onShowGridAreaHighlight: PropTypes.func.isRequired,
+    onShowGridCellHighlight: PropTypes.func.isRequired,
   },
 
   mixins: [ addons.PureRenderMixin ],
 
   getInitialState() {
     return {
       selectedGrids: [],
     };
@@ -70,17 +71,18 @@ module.exports = createClass({
    *
    * @param  {Object} grid
    *         A single grid container in the document.
    */
   renderGrid(grid) {
     const { id, color, gridFragments } = 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 { rows, cols, areas } = gridFragments[0];
+    let gridFragmentIndex = 0;
+    const { rows, cols, areas } = gridFragments[gridFragmentIndex];
     const numberOfColumns = cols.lines.length - 1;
     const numberOfRows = rows.lines.length - 1;
     const rectangles = [];
 
     // Draw a rectangle that acts as a border for the grid outline.
     const border = this.renderGridOutlineBorder(numberOfRows, numberOfColumns, color);
     rectangles.push(border);
 
@@ -89,17 +91,17 @@ module.exports = createClass({
     const width = 10;
     const height = 10;
 
     // Draw the cells within the grid outline border.
     for (let rowNumber = 1; rowNumber <= numberOfRows; rowNumber++) {
       for (let columnNumber = 1; columnNumber <= numberOfColumns; columnNumber++) {
         const gridAreaName = this.getGridAreaName(columnNumber, rowNumber, areas);
         const gridCell = this.renderGridCell(id, x, y, rowNumber, columnNumber, color,
-          gridAreaName);
+          gridAreaName, gridFragmentIndex);
 
         rectangles.push(gridCell);
         x += width;
       }
 
       x = 1;
       y += height;
     }
@@ -117,23 +119,29 @@ module.exports = createClass({
    * @param  {Number} y
    *         The y-position of the grid cell.
    * @param  {Number} rowNumber
    *         The row number of the grid cell.
    * @param  {Number} columnNumber
    *         The column number of the grid cell.
    * @param  {String|null} gridAreaName
    *         The grid area name or null if the grid cell is not part of a grid area.
+   * @param  {Number} gridFragmentIndex
+   *         The index of the grid fragment rendered to the document.
    */
-  renderGridCell(id, x, y, rowNumber, columnNumber, color, gridAreaName) {
+  renderGridCell(id, x, y, rowNumber, columnNumber, color, gridAreaName,
+    gridFragmentIndex) {
     return dom.rect(
       {
         className: "grid-outline-cell",
         "data-grid-area-name": gridAreaName,
+        "data-grid-fragment-index": gridFragmentIndex,
         "data-grid-id": id,
+        "data-grid-row": rowNumber,
+        "data-grid-column": columnNumber,
         x,
         y,
         width: 10,
         height: 10,
         fill: "none",
         stroke: color,
         onMouseOver: this.onMouseOverCell,
         onMouseOut: this.onMouseLeaveCell,
@@ -162,37 +170,50 @@ module.exports = createClass({
       }
     );
   },
 
   onMouseLeaveCell({ target }) {
     const {
       grids,
       onShowGridAreaHighlight,
+      onShowGridCellHighlight,
     } = this.props;
     const id = target.getAttribute("data-grid-id");
     const color = target.getAttribute("stroke");
 
     target.setAttribute("fill", "none");
 
     onShowGridAreaHighlight(grids[id].nodeFront, null, color);
+    onShowGridCellHighlight(grids[id].nodeFront, null, null, null);
   },
 
   onMouseOverCell({ target }) {
     const {
       grids,
       onShowGridAreaHighlight,
+      onShowGridCellHighlight,
     } = this.props;
     const name = target.getAttribute("data-grid-area-name");
     const id = target.getAttribute("data-grid-id");
+    const fragmentIndex = target.getAttribute("data-grid-fragment-index");
     const color = target.getAttribute("stroke");
+    const rowNumber = target.getAttribute("data-grid-row");
+    const columnNumber = target.getAttribute("data-grid-column");
 
     target.setAttribute("fill", color);
 
-    onShowGridAreaHighlight(grids[id].nodeFront, name, color);
+    if (name) {
+      onShowGridAreaHighlight(grids[id].nodeFront, name, color);
+    }
+
+    if (fragmentIndex && rowNumber && columnNumber) {
+      onShowGridCellHighlight(grids[id].nodeFront, fragmentIndex,
+        rowNumber, columnNumber);
+    }
   },
 
   render() {
     return this.state.selectedGrids.length ?
       dom.svg(
         {
           className: "grid-outline",
           width: "100%",
--- a/devtools/client/inspector/grids/grid-inspector.js
+++ b/devtools/client/inspector/grids/grid-inspector.js
@@ -46,16 +46,17 @@ function GridInspector(inspector, window
   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.onShowGridCellHighlight = this.onShowGridCellHighlight.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();
 }
 
@@ -113,16 +114,17 @@ GridInspector.prototype = {
 
   getComponentProps() {
     return {
       getSwatchColorPickerTooltip: this.getSwatchColorPickerTooltip,
       setSelectedNode: this.setSelectedNode,
       onSetGridOverlayColor: this.onSetGridOverlayColor,
       onShowBoxModelHighlighterForNode: this.onShowBoxModelHighlighterForNode,
       onShowGridAreaHighlight: this.onShowGridAreaHighlight,
+      onShowGridCellHighlight: this.onShowGridCellHighlight,
       onToggleGridHighlighter: this.onToggleGridHighlighter,
       onToggleShowGridLineNumbers: this.onToggleShowGridLineNumbers,
       onToggleShowInfiniteLines: this.onToggleShowInfiniteLines,
     };
   },
 
   /**
    * Returns the color set for the grid highlighter associated with the provided
@@ -320,16 +322,39 @@ GridInspector.prototype = {
 
     highlighterSettings.showGridArea = gridAreaName;
     highlighterSettings.color = color;
 
     this.highlighters.showGridHighlighter(node, highlighterSettings);
   },
 
   /**
+   * Highlights the grid cell 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  {Number|null} gridFragmentIndex
+   *         The index of the grid fragment for which the grid highlighter
+   *         is highlighted for.
+   * @param  {Number|null} rowNumber
+   *         The row number of the grid cell for which the grid highlighter
+   *         is highlighted for.
+   * @param  {Number|null} columnNumber
+   *         The column number of the grid cell for which the grid highlighter
+   *         is highlighted for.
+   */
+  onShowGridCellHighlight(node, gridFragmentIndex, rowNumber, columnNumber) {
+    let { highlighterSettings } = this.store.getState();
+    highlighterSettings.showGridCell = { gridFragmentIndex, rowNumber, columnNumber };
+
+    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);
--- a/devtools/client/inspector/layout/layout.js
+++ b/devtools/client/inspector/layout/layout.js
@@ -39,16 +39,17 @@ LayoutView.prototype = {
     } = this.inspector.boxmodel.getComponentProps();
 
     let {
       getSwatchColorPickerTooltip,
       setSelectedNode,
       onSetGridOverlayColor,
       onShowBoxModelHighlighterForNode,
       onShowGridAreaHighlight,
+      onShowGridCellHighlight,
       onToggleGridHighlighter,
       onToggleShowGridLineNumbers,
       onToggleShowInfiniteLines,
     } = this.inspector.gridInspector.getComponentProps();
 
     let app = App({
       getSwatchColorPickerTooltip,
       setSelectedNode,
@@ -65,16 +66,17 @@ LayoutView.prototype = {
       showGridOutline: Services.prefs.getBoolPref(SHOW_GRID_OUTLINE_PREF),
 
       onHideBoxModelHighlighter,
       onSetGridOverlayColor,
       onShowBoxModelEditor,
       onShowBoxModelHighlighter,
       onShowBoxModelHighlighterForNode,
       onShowGridAreaHighlight,
+      onShowGridCellHighlight,
       onToggleGridHighlighter,
       onToggleShowGridLineNumbers,
       onToggleShowInfiniteLines,
     });
 
     let provider = createElement(Provider, {
       store: this.store,
       id: "layoutview",
--- a/devtools/server/actors/highlighters/css-grid.js
+++ b/devtools/server/actors/highlighters/css-grid.js
@@ -498,16 +498,17 @@ CssGridHighlighter.prototype = extend(Au
     root.setAttribute("style", "display: none");
     this.currentNode.offsetWidth;
 
     let { width, height } = getWindowDimensions(this.win);
 
     // Clear the canvas the grid area highlights.
     this.clearCanvas(width, height);
     this.clearGridAreas();
+    this.clearGridCell();
 
     // Start drawing the grid fragments.
     for (let i = 0; i < this.gridData.length; i++) {
       let fragment = this.gridData[i];
       let quad = this.currentQuads.content[i];
       this.renderFragment(fragment, quad);
     }
 
@@ -874,16 +875,17 @@ CssGridHighlighter.prototype = extend(Au
    *         Index of the grid fragment to render the grid cell highlight.
    * @param  {Number} rowNumber
    *         Row number of the grid cell to highlight.
    * @param  {Number} columnNumber
    *         Column number of the grid cell to highlight.
    */
   renderGridCell(gridFragmentIndex, rowNumber, columnNumber) {
     let fragment = this.gridData[gridFragmentIndex];
+
     if (!fragment) {
       return;
     }
 
     let row = fragment.rows.tracks[rowNumber - 1];
     let column = fragment.cols.tracks[columnNumber - 1];
 
     if (!row || !column) {